// This code was generated by the Gardens Point Parser Generator
// Copyright (c) Wayne Kelly, QUT 2005-2007
// (see accompanying GPPGcopyright.rtf)

// GPPG version 1.2.0.115 (2007-11-7)
// options: no-lines


using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using gppg;
using analex;
using SymbolTable;
using System.IO;

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

public class Interpreter
{
    public static CSymbolTable mST = new CSymbolTable();
    public static ArrayList mCSCode = new ArrayList();

    public static ArrayList mCSCodeFields = new ArrayList();
    public static ArrayList mCSCodeInitialize = new ArrayList();
    public static ArrayList mCSCodeUpdate = new ArrayList();
    public static ArrayList mCSCodeMethods = new ArrayList();

    public static Assembly compiledAssembly;
    public static object compiledScript;

    public static ArrayList errors = new ArrayList();

    public static ArrayList productions = new ArrayList();

    static public bool CompileScript(string sourceFile, string databaseFile)
    {
        errors.Clear();
        mST.mSymbolTable.Clear();
        mCSCode.Clear();
        mCSCodeFields.Clear();
        mCSCodeInitialize.Clear();
        mCSCodeMethods.Clear();
        mCSCodeUpdate.Clear();
        productions.Clear();

        ParseCode(databaseFile, sourceFile);

        if (errors.Count > 0)
        {
            return false;
        }

        CompilerResults cr = null;
        try
        {
            string cs = GetGeneratedCSharpCode();
            File.WriteAllText("cs_code.cs", cs);

            compiledAssembly = EVEDemo.CodeCompiler.CompileCode(cs, ref cr);

            compiledScript = EVEDemo.CodeCompiler.Execute(compiledAssembly, "EVEDemo.Script", "CreateScriptInstance");
        }
        catch (Exception ex)
        {
            errors.Add(ex.Message);
            if (cr != null)
            {
                foreach (CompilerError err in cr.Errors)
                {
                    errors.Add(err.ToString());
                    //MessageBox.Show(err.ToString());
                }
            }
            return false;
        }

        return true;
    }

    static void MainTest(string[] args)
    {
        ParseCode("sample.txt", "test.txt");

        ArrayList symbols = GetSymbolsFromTable();

        foreach (object li in symbols)
        {
            ArrayList l = (ArrayList)li;
            System.Console.WriteLine("-----");
            foreach (object s in l)
            {
                string str = (string)s;
                System.Console.WriteLine(str);
            }
        }
    }

    public static void ParseCode(string fDataBase, string fScript)
    {
        Parser parser = new Parser();

        parser.scanner = new Parser.Scanner(fDataBase);
        //parser.Trace = true;

        try
        {
            parser.Parse();
        }
        catch (FormatException e)
        {
            //Console.WriteLine("wrong value");
            errors.Add("wrong Value...");
            return;
        }
        catch (Exception e)
        {
            //System.Console.WriteLine(e);
            errors.Add(e);
            return;
        }


        parser.scanner = new Parser.Scanner(fScript);
        //parser.Trace = true;
        try
        {
            parser.Parse();
        }
        catch (FormatException e)
        {
            errors.Add("wrong Value...");
            return;
        }
        catch (Exception e)
        {
            errors.Add(e);
            return;
        }
    }

    public static ArrayList GetSymbolsFromTable()
    {
        ArrayList retArray = new ArrayList();

        foreach (ISymbolStructure symbol in mST.mSymbolTable.Values)
        {
            ArrayList newSymbol = new ArrayList();
            retArray.Add(newSymbol);

            newSymbol.Add("# symbol identifier: " + symbol.Ident);
            switch (symbol.SymbolType)
            {
                case ESymbolType.ST_Var:
                    {
                        CVarInfo var = (CVarInfo)symbol;
                        if (var.Owner == null)
                        {
                            newSymbol.Add("symbol declaration level: " + var.DeclarationLvl.ToString());
                            newSymbol.Add("symbol type: " + var.SymbolType.ToString());
                            newSymbol.Add("is const: " + var.IsConst);
                        }
                        else if (var.Owner.SymbolType == ESymbolType.ST_Func)
                        {
                            newSymbol.Add("is local variable of: " + var.Owner.Ident);
                            newSymbol.Add("is const: " + var.IsConst);
                            newSymbol.Add("is parameter: " + var.IsParam);
                        }
                    }
                    break;

                case ESymbolType.ST_Record:
                    {
                        CRecordInfo rec = (CRecordInfo)symbol;
                        newSymbol.Add("symbol declaration level: " + rec.DeclarationLvl.ToString());
                        newSymbol.Add("symbol type: " + rec.SymbolType.ToString());
                        newSymbol.Add("contains: " + rec.VarCount + " variables");

                        foreach (CVarInfo var in rec.VarList)
                        {
                            newSymbol.Add("# symbol identifier: " + var.Ident);
                            newSymbol.Add("symbol declaration level: " + var.DeclarationLvl.ToString());
                            newSymbol.Add("symbol type: " + var.SymbolType.ToString());
                            newSymbol.Add("is const: " + var.IsConst);
                            newSymbol.Add("$");
                        }
                    }
                    break;

                case ESymbolType.ST_Func:
                    {
                        CFuncInfo func = (CFuncInfo)symbol;
                        newSymbol.Add("symbol type: " + func.SymbolType.ToString());
                        newSymbol.Add("return value: " + func.RetType.ToString());
                        newSymbol.Add("has: " + func.GetArgCount + " parameters");
                        foreach (CVarInfo var in func.Arguments)
                        {
                            newSymbol.Add("# symbol identifier: " + var.Ident);
                            newSymbol.Add("symbol declaration level: " + var.DeclarationLvl.ToString());
                            newSymbol.Add("symbol type: " + var.SymbolType.ToString());
                            newSymbol.Add("$");
                        }
                        newSymbol.Add("contains: " + func.GetArgCount + " variables");
                        foreach (CVarInfo var in func.Vars)
                        {
                            newSymbol.Add("# symbol identifier: " + var.Ident);
                            newSymbol.Add("symbol declaration level: " + var.DeclarationLvl.ToString());
                            newSymbol.Add("symbol type: " + var.SymbolType.ToString());
                            newSymbol.Add("is const: " + var.IsConst);
                            newSymbol.Add("$");
                        }
                    }
                    break;
            }
            newSymbol.Add("$");
        }

        return retArray;

    }

    public static string GetGeneratedCSharpCode()
    {
        /*mCSCodeFields.Add("int a;");
        mCSCodeInitialize.Add("blabla();");
        mCSCodeUpdate.Add("a = blabla();");
        mCSCodeMethods.Add("public int blabla()");
        mCSCodeMethods.Add("\tint t = 0;");
        mCSCodeMethods.Add("}");
        */

        StringBuilder csCode = new StringBuilder();
        csCode.Append(@"#region Using Statements
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;

using EVE;
using EVE.EVEObjects;
using EVE.EVEShaders;
using EVE.EVECameras;
using EVE.EVEOctrees;

#endregion

namespace EVEDemo
{
    public class Script
    {"
            );
        csCode.Append('\n');

        foreach (string y in mCSCodeFields)
        {
            csCode.Append("\t");
            csCode.Append(y);
            csCode.Append('\n');
        }

        csCode.Append(@"        public static object CreateScriptInstance()
        {
            return new Script();
        }

        public void Initialize()
        {"
        );

        csCode.Append('\n');

        foreach (string y in mCSCodeInitialize)
        {
            csCode.Append("\t");
            csCode.Append(y);
            csCode.Append('\n');
        }

        csCode.Append(@"        }");

        //public void Update()
        //{"
        //);

        //csCode.Append('\n');

        foreach (string y in mCSCodeUpdate)
        {
            csCode.Append("\t");
            csCode.Append(y);
            csCode.Append('\n');
        }

        //csCode.Append("\t}\n\n");

        foreach (string y in mCSCodeMethods)
        {
            csCode.Append("\t");
            csCode.Append(y);
            csCode.Append('\n');
        }

        csCode.Append("\n\t}\n}");

        return csCode.ToString();
    }
}