using System;
using System.Collections.Generic;
using System.Text;

namespace Halo3Map.Scripting
{
    public class Syntax
    {
        public List<SyntaxChunk> chunks;
        public string scriptText;
        public Script script;
    }

    public class SyntaxChunk
    {
        public SyntaxChunk parent;
        public SyntaxChunk child;
        public SyntaxChunk sibling;

        public int syntaxNumber;

        public ReturnType returnType;

        public ScriptString scriptString;

        public SyntaxChunk(ref ScriptsData sd, ref Syntax syntax, int chunknum, string indent)
        {
            syntaxNumber = chunknum;
            bool firstChunk = syntax.chunks.Count == 0;
            syntax.chunks.Add(this);
            ScriptSyntax chunk = sd.scryptsyntax[chunknum];

            if (chunk.ExpressionType == 8 || chunk.ExpressionType == 10)
            {
                if (chunk.ValueType == 4 || firstChunk)
                {
                    syntax.scriptText += "\r\n" + indent + "(";
                    indent += ' ';
                }
                else { syntax.scriptText += "("; }
                
                byte[] temp = chunk.Value;
                Array.Reverse(temp);
                int nextChunk = BitConverter.ToInt16(temp, 0);
                child = new SyntaxChunk(ref sd, ref syntax, nextChunk, indent);

                if (chunk.ValueType == 4)
                {
                    indent = indent.Remove(0, 1);
                    if (chunk.Indentity <= 1 || firstChunk || syntax.scriptText.Substring(syntax.scriptText.Length - 2, 1) == ")")
                    {
                        syntax.scriptText += "\r\n" + indent + ")";
                    }
                }

                if ((chunk.Indentity <= 1 || chunk.ExpressionType != 8) && !firstChunk && syntax.scriptText.Substring(syntax.scriptText.Length - 2, 1) != ")")
                {
                    syntax.scriptText += ")";
                    if (chunk.SiblingIndex != -1)
                    {
                        syntax.scriptText += " ";
                    }
                }
                else if (chunk.Indentity <= 1 && (int)chunk.ValueType != 4)
                {
                    syntax.scriptText += "\r\n" + indent + ")";
                }
            }
            else
            {
                returnType = (ReturnType)chunk.ValueType;
                if ((int)returnType > 4 && (int)returnType < 9)
                {
                    switch ((int)returnType)
                    {
                        case 5:
                            syntax.scriptText += BitConverter.ToBoolean(chunk.Value, 0).ToString();
                            break;
                        case 6:
                            syntax.scriptText += BitConverter.ToSingle(chunk.Value, 0).ToString();
                            break;
                        case 7:
                            syntax.scriptText += BitConverter.ToInt16(chunk.Value, 0).ToString();
                            break;
                        case 8:
                            syntax.scriptText += BitConverter.ToInt32(chunk.Value, 0).ToString();
                            break;
                    }
                }
                else
                {
                    scriptString = new ScriptString(chunk.ScriptStringOffset);
                    if ((int)returnType == 9)
                        scriptString.cmd = "\"" + scriptString.cmd + "\"";

                    if ((int)returnType == 12)
                    {
                        string todisp = scriptString.cmd + '\t';
                        for (int i = 0; i < 4; i++)
                            todisp += string.Format("{0:X}", chunk.Value[i].ToString()) + " ";
                        System.Diagnostics.Debug.WriteLine(todisp);
                    }

                    syntax.scriptText += scriptString.cmd;
                }

                if (chunk.SiblingIndex != -1)
                    syntax.scriptText += " ";
            }
            if (chunk.SiblingIndex != -1)
            {
                int nextChunk = chunk.SiblingIndex;
                sibling = new SyntaxChunk(ref sd, ref syntax, nextChunk, indent);
            }
        }
    }
}
