using System;
using System.Collections.Generic;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using System.CodeDom;
using System.CodeDom.Compiler;
using System.Runtime.CompilerServices;
using System.Reflection;
using Microsoft.CSharp;
using System.Security.Permissions;
using System.IO;

namespace EVEDemo
{
    public delegate void AfterCompileDelegate();

    public partial class EveForm : Form
    {
        public AfterCompileDelegate afterCompile;
        public Assembly compiledAssembly;
        public object compiledScript;
        private string sourceFile;
        private string databaseFile;
        
        public EveForm()
        {
            InitializeComponent();
        }

        public void CompileScript()
        {
            // save both main script and the database:
            File.WriteAllLines(sourceFile, editorRichEdit.Lines);
            File.WriteAllLines(databaseFile, editorRichEdit2.Lines);
            resultList.Items.Clear();

            if (Interpreter.CompileScript(sourceFile, databaseFile) == true)
            {
                compiledAssembly = Interpreter.compiledAssembly;
                compiledScript = Interpreter.compiledScript;

                afterCompile();

                resultList.Items.Add("Comppilation Done! :)");

                FillTreeView(Interpreter.GetSymbolsFromTable());
            }
            else
            {
                foreach (object o in Interpreter.errors)
                {
                    resultList.Items.Add(o.ToString());
                    MessageBox.Show(o.ToString());
                }
            }
        }

        public void CompileSurce()
        {
            resultList.Items.Clear();
            CompilerResults cr = null;
            try
            {
                
                StringBuilder sb = new StringBuilder();

                for (int i = 0; i < editorRichEdit.Lines.Length; ++i)
                {
                    sb.Append(editorRichEdit.Lines[i]);
                    sb.Append("\n");
                }

                compiledAssembly = CodeCompiler.CompileCode(sb.ToString(), ref cr);

                compiledScript = CodeCompiler.Execute(compiledAssembly, "EVEDemo.Script", "CreateScriptInstance");

                resultList.Items.Add("compilation done!");

                afterCompile();
            }
            catch (Exception ex)
            {
                resultList.Items.Add(ex.Message);
                if (cr != null)
                {
                    resultList.Items.Clear();
                    foreach (CompilerError err in cr.Errors)
                    {
                        resultList.Items.Add(err.ToString());
                        //MessageBox.Show(err.ToString());
                    }
                }
            }
        }

        private void FillTreeView(ArrayList list)
        {
            treeView.Nodes.Clear();
         
            int nodeId = 0;
            Stack<TreeNode> stack = new Stack<TreeNode>();
            foreach (object o in list)
            {
                ArrayList lnode = (ArrayList)o;
                string s;

                int position = 0;

                s = lnode[position].ToString();
                if (s[0] == '#')
                {
                    s = s.Replace("# symbol identifier: ", "");
                }
                treeView.Nodes.Add(s);
                stack.Clear();
                stack.Push(treeView.Nodes[nodeId]);

                ++position;
                while (position < lnode.Count)
                {
                    s = lnode[position].ToString();
                    if (s[0] == '$')
                    {
                        stack.Pop();
                    }
                    else if (s[0] == '#')
                    {
                        s = s.Replace("# symbol identifier: ", "");
                        stack.Push(stack.Peek().Nodes.Add(s));
                    }
                    else
                    {
                        stack.Peek().Nodes.Add(s);
                    }
                    ++position;
                }
                ++nodeId;
            }
        }

        private void compileBtn_Click(object sender, EventArgs e)
        {
            CompileScript();  
        }

        private void loadBtn_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlgOpen = new OpenFileDialog();
            dlgOpen.FileName = sourceFile;
            if (dlgOpen.ShowDialog() == DialogResult.OK)
            {
                editorRichEdit.Lines = File.ReadAllLines(dlgOpen.FileName);
                sourceFile = dlgOpen.FileName;
            }
        }

        public void LoadSource(string fname, string fdatabase)
        {
            editorRichEdit.Lines = File.ReadAllLines(fname);
            sourceFile = fname;
            editorRichEdit2.Lines = File.ReadAllLines(fdatabase);
            databaseFile = fdatabase;
        }

        private void saveScriptBtn_Click(object sender, EventArgs e)
        {
            SaveFileDialog saveDlg = new SaveFileDialog();
            saveDlg.FileName = sourceFile;
            if (saveDlg.ShowDialog() == DialogResult.OK)
            {
                File.WriteAllLines(saveDlg.FileName, editorRichEdit.Lines);
            }
        }

        private void trackBar1_Scroll(object sender, EventArgs e)
        {
            this.Opacity = (double)trackBar1.Value/100.0;
        }

        private void EveForm_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)Keys.F5)
            {
                CompileSurce();
            }
        }

        private void saveScriptBtn2_Click(object sender, EventArgs e)
        {
            SaveFileDialog saveDlg = new SaveFileDialog();
            saveDlg.FileName = databaseFile;
            if (saveDlg.ShowDialog() == DialogResult.OK)
            {
                File.WriteAllLines(saveDlg.FileName, editorRichEdit2.Lines);
            }
        }

        private void loadBtn2_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlgOpen = new OpenFileDialog();
            dlgOpen.FileName = databaseFile;
            if (dlgOpen.ShowDialog() == DialogResult.OK)
            {
                editorRichEdit2.Lines = File.ReadAllLines(dlgOpen.FileName);
                databaseFile = dlgOpen.FileName;
            }
        }
    }
}