using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.VisualBasic;
using IO;

namespace HaloPlugins
{
    public class TagReference : IMetaNode
    {
        int Index = -1, Id = -1;
        string Name = "TagReference", Class = "", Tag = "Null Reference";
        HaloEngine Engine = HaloEngine.Halo2;

        public TagReference(string Name, string Class)
        {
            this.Name = Name;
            this.Class = Class;
        }

        public TagReference(string Name, string Class, HaloEngine Engine)
        {
            this.Name = Name;
            this.Class = Class;
            this.Engine = Engine;
        }

        #region MetaNode Members

        public void Read(EndianReader br)
        {
            Class = Strings.StrReverse(new string(Encoding.ASCII.GetChars(br.ReadBytes(4))));
            if (Engine != HaloEngine.Halo2)
                br.BaseStream.Position += 8;
            Index = Id = br.ReadInt32();
            if (Index != -1)
                Tag = ((Dictionary<string, int>)EngineManager.GetEngine()[EngineManager.EngineId]["TagIds"]).Keys.ElementAt(Index);
        }

        public void Read(EndianReader br, int Magic)
        {
            Class = Strings.StrReverse(new string(Encoding.ASCII.GetChars(br.ReadBytes(4))));
            if (Engine != HaloEngine.Halo2)
                br.BaseStream.Position += 8;
            Index = Id = br.ReadInt32();

            // Add
            if (Index != -1)
            {
                Tag = ((Dictionary<string, int>)EngineManager.GetEngine()[EngineManager.EngineId]["TagIds"]).Keys.ElementAt(Index & 0xFFFF);
            }
        }

        public void Write(EndianWriter bw)
        {
            // Add
            if (Tag != "Null Reference")
            {
                try { Index = ((Dictionary<string, int>)EngineManager.GetEngine()[EngineManager.EngineId]["TagIds"])[Tag]; }
                catch
                {
                    Index = ((Dictionary<string, int>)EngineManager.GetEngine()[EngineManager.EngineId]["TagIds"]).Count;
                    ((Dictionary<string, int>)EngineManager.GetEngine()[EngineManager.EngineId]["TagIds"]).Add(Tag, Index);
                }

                // Get class
                Class = EngineManager.GetEngine()[EngineManager.EngineId]["Class", Tag.Substring(Tag.LastIndexOf(".") + 1)];
            }
            else
                Index = -1;

            bw.Write(Strings.StrReverse(Class).ToCharArray());
            if (Engine != HaloEngine.Halo2)
                bw.Write((long)0);
            bw.Write(Index);
        }

        public object GetValue()
        {
            return Tag;
        }

        public void SetValue(object Value)
        {
            Tag = (string)Value;
        }

        public int GetSize()
        {
            return Engine == HaloEngine.Halo2 ? 8 : 16;
        }

        public void Compile(EndianWriter bw, int Magic)
        {
            if (Tag != "Null Reference")
                Id = ((Dictionary<string, int>)EngineManager.GetEngine()[EngineManager.EngineId]["TagIds"])[Tag];
            else
                Id = -1;

            bw.Write(Strings.StrReverse(Class).ToCharArray());
            if (Engine != HaloEngine.Halo2)
                bw.Write((long)0);
            bw.Write(Id);
        }

        public void Decompile(EndianWriter bw, int Magic)
        {
            // Add
            if (Tag != "Null Reference")
            {
                try { Index = ((Dictionary<string, int>)EngineManager.GetEngine()[EngineManager.EngineId]["TagIds"])[Tag]; }
                catch
                {
                    Index = ((Dictionary<string, int>)EngineManager.GetEngine()[EngineManager.EngineId]["TagIds"]).Count;
                    ((Dictionary<string, int>)EngineManager.GetEngine()[EngineManager.EngineId]["TagIds"]).Add(Tag, Index);
                }

                // Get class
                Class = EngineManager.GetEngine()[EngineManager.EngineId]["Class", Tag.Substring(Tag.LastIndexOf(".") + 1)];
            }
            else
                Index = -1;

            bw.Write(Strings.StrReverse(Class).ToCharArray());
            if (Engine != HaloEngine.Halo2)
                bw.Write((long)0);
            bw.Write(Index);
        }

        public string GetName()
        {
            return Name;
        }

        #endregion

        #region ICloneable Members

        public object Clone()
        {
            TagReference t = new TagReference(this.Name, this.Class, this.Engine);
            t.Index = Index;
            t.Tag = Tag;
            t.Id = Id;
            return t;
        }

        #endregion

        #region TagReferences Members

        public int GetId()
        {
            return Id & 0xFFFF;
        }

        public string GetFileName()
        {
            return Tag;
        }

        #endregion

        #region ToString

        public override string ToString()
        {
            return "TagReference: " + Name + ", Class: " + Class + ", Index: " + Index.ToString() + ", Tag: " + Tag;
        }

        #endregion
    }
}
