using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Reflection;
using DevExpress;
using DevExpress.XtraTab;
using System.Collections;
using DevExpress.XtraNavBar;
using Global;
using HaloPlugins;

namespace HaloControls
{
    public partial class TagBlock : UserControl
    {
        public int Index;
        int OldIndex = 0;
        bool Expanded = true, Loading = true;
        HaloPlugins.TagBlock tagblock;

        public TagBlock(string Description, HaloPlugins.TagBlock tagblock, int Index)
        {
            InitializeComponent();
            this.Index = Index;
            this.tagblock = tagblock;
            groupControl1.Text = Description;
            this.panelControl2.AutoSize = true;
        }

        private void Reflexive_Load(object sender, EventArgs ea)
        {
            // Collapse Panel
            button1_Click(null, null);

            // Add end block
            EndReflexive er = new EndReflexive(groupControl1.Text, DockStyle.Top);
            panelControl2.Controls.Add(er);

            // Load Controls
            IMetaNode[] Fields = (IMetaNode[])tagblock.GetValue();
            for (int i = Fields.Length - 1; i >= 0; i--)
            {
                if (Fields[i].GetType() == typeof(HaloPlugins.Value))
                {
                    Value v = new Value(((HaloPlugins.Value)Fields[i]).GetName(), ((HaloPlugins.Value)Fields[i]).GetValue(), i);
                    v.Dock = DockStyle.Top;
                    panelControl2.Controls.Add(v);
                }
                else if (Fields[i].GetType() == typeof(HaloPlugins.Flags))
                {
                    Bitmask b = new Bitmask(((HaloPlugins.Flags)Fields[i]).GetName(), ((HaloPlugins.Flags)Fields[i]).GetOptions(), ((HaloPlugins.Flags)Fields[i]).GetValue(), ((HaloPlugins.Flags)Fields[i]).GetBitCount(), i);
                    b.Dock = DockStyle.Top;
                    panelControl2.Controls.Add(b);
                }
                else if (Fields[i].GetType() == typeof(HaloPlugins.Enum))
                {
                    Enum b = new Enum(((HaloPlugins.Enum)Fields[i]).GetName(), ((HaloPlugins.Enum)Fields[i]).GetOptions(), ((HaloPlugins.Enum)Fields[i]).GetValue(), ((HaloPlugins.Enum)Fields[i]).GetBitCount(), i);
                    b.Dock = DockStyle.Top;
                    panelControl2.Controls.Add(b);
                }
                else if (Fields[i].GetType() == typeof(HaloPlugins.LongString)
                    || Fields[i].GetType() == typeof(HaloPlugins.ShortString)
                    || Fields[i].GetType() == typeof(HaloPlugins.Tag))
                {
                    HaloControls.String s = new String(Fields[i].GetName(), Fields[i].GetValue(), Fields[i].GetSize(), i);
                    s.Dock = DockStyle.Top;
                    panelControl2.Controls.Add(s);
                }
                else if (Fields[i].GetType() == typeof(HaloPlugins.StringId))
                {
                    HaloControls.String s = new String(Fields[i].GetName(), Fields[i].GetValue(), 128, i);
                    s.Dock = DockStyle.Top;
                    panelControl2.Controls.Add(s);
                }
                else if (Fields[i].GetType() == typeof(HaloPlugins.TagIndex)
                    || Fields[i].GetType() == typeof(HaloPlugins.TagReference))
                {
                    HaloControls.TagReference t = new TagReference(Fields[i].GetName(), (string)Fields[i].GetValue(), i);
                    t.Dock = DockStyle.Top;
                    panelControl2.Controls.Add(t);
                }
                else if (Fields[i].GetType() == typeof(HaloPlugins.TagBlock))
                {
                    HaloControls.TagBlock r = new TagBlock(Fields[i].GetName(), (HaloPlugins.TagBlock)Fields[i], i);
                    r.Dock = DockStyle.Top;
                    panelControl2.Controls.Add(r);
                }
            }

            // Setup combo box
            if (tagblock.BlockCount > 0)
            {
                // Add block numbers
                for (int i = 0; i < tagblock.BlockCount; i++)
                    comboBox1.Items.Add(i.ToString());

                comboBox1.SelectedIndex = 0;
            }
            else
            {
                panelControl2.Enabled = false;
                btnExpand.Enabled = false;
            }

            // Done
            Loading = false;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (Expanded)
            {
                panelControl2.Visible = false;
                Expanded = false;
            }
            else
            {
                panelControl2.Visible = true;
                Expanded = true;
            }
        }

        private void btnAddChunk_Click(object sender, EventArgs e)
        {
            // Add Chunk
            tagblock.AddBlock();

            // Save values
            if (tagblock.BlockCount > 1)
            {
                OldIndex = comboBox1.SelectedIndex;
                SaveValues(OldIndex);
            }

            // Update ComboBox
            comboBox1.Items.Add(comboBox1.Items.Count.ToString());
            comboBox1.SelectedIndex = comboBox1.Items.Count - 1;

            // Update controls
            UpdateValues();

            // Make sure the Panel Is Enabled
            panelControl2.Enabled = true;
            panelControl2.Visible = true;
            Expanded = true;
            btnExpand.Enabled = true;
        }

        private void btnDeleteChunk_Click(object sender, EventArgs e)
        {
            // Check
            if (tagblock.BlockCount > 0)
                return;

            // Remove Chunk
            OldIndex = comboBox1.SelectedIndex;
            tagblock.RemoveBlock(comboBox1.SelectedIndex);

            // Update ComboBox
            comboBox1.Items.Clear();
            for (int i = 0; i < tagblock.BlockCount; i++)
                comboBox1.Items.Add(i.ToString());

            // Selete Near Index
            if (OldIndex <= tagblock.BlockCount - 1)
                comboBox1.SelectedIndex = OldIndex;
            else if (OldIndex - 1 <= tagblock.BlockCount - 1)
                comboBox1.SelectedIndex = OldIndex - 1;
            else
                comboBox1.Text = "";

            // Double Check
            if (tagblock.BlockCount == 0)
            {
                btnExpand.Enabled = false;
                panelControl2.Enabled = false;
                panelControl2.Visible = false;
                Expanded = false;
            }
        }

        private void btnDeleteAllChunks_Click(object sender, EventArgs e)
        {
            // Update Form
            comboBox1.Items.Clear();
            comboBox1.Text = "";
            btnExpand.Enabled = false;
            panelControl2.Enabled = false;
            panelControl2.Visible = false;
            Expanded = false;
            OldIndex = 0;

            // Clear Reflexive
            tagblock.RemoveAll();
        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            //Double Check
            if (Loading)
                return;

            // Save Old Values
            SaveValues(OldIndex);

            // Update
            OldIndex = comboBox1.SelectedIndex;
            UpdateValues();

            // Resume
            panelControl2.ResumeLayout();
        }

        public void Reload(object Value)
        {
            tagblock = (HaloPlugins.TagBlock)Value;
            if (tagblock.BlockCount > 0)
            {
                //Set Loading
                Loading = true;

                //Change Index
                comboBox1.Items.Clear();
                for (int i = 0; i < tagblock.BlockCount; i++)
                {
                    comboBox1.Items.Add(i.ToString());
                }
                comboBox1.SelectedIndex = 0;
                OldIndex = 0;

                // Update values
                UpdateValues();

                // Done
                Loading = false;
            }
            else
            {
                comboBox1.Items.Clear();
                comboBox1.Text = "";
                btnExpand.Enabled = false;
                panelControl2.Enabled = false;
                panelControl2.Visible = false;
                Expanded = false;
            }
        }

        public object Save()
        {
            // Sanity Check
            if (tagblock.BlockCount == 0)
                return tagblock;

            // Save values
            SaveValues(comboBox1.SelectedIndex);

            // We return nothing
            return null;
        }

        void UpdateValues()
        {
            int Field = 0;
            for (int i = 0; i < panelControl2.Controls.Count; i++)
            {
                if (panelControl2.Controls[i].GetType() == typeof(Value))
                {
                    Field = ((Value)(panelControl2.Controls[i])).Index;
                    ((Value)(panelControl2.Controls[i])).Reload(tagblock[comboBox1.SelectedIndex][Field].GetValue());
                }
                else if (panelControl2.Controls[i].GetType() == typeof(String))
                {
                    Field = ((String)(panelControl2.Controls[i])).Index;
                    ((String)(panelControl2.Controls[i])).Reload(tagblock[comboBox1.SelectedIndex][Field].GetValue());
                }
                else if (panelControl2.Controls[i].GetType() == typeof(Enum))
                {
                    Field = ((Enum)(panelControl2.Controls[i])).Index;
                    ((Enum)(panelControl2.Controls[i])).Reload(tagblock[comboBox1.SelectedIndex][Field].GetValue());
                }
                else if (panelControl2.Controls[i].GetType() == typeof(Bitmask))
                {
                    Field = ((Bitmask)(panelControl2.Controls[i])).Index;
                    ((Bitmask)(panelControl2.Controls[i])).Reload(tagblock[comboBox1.SelectedIndex][Field].GetValue());
                }
                else if (panelControl2.Controls[i].GetType() == typeof(TagReference))
                {
                    Field = ((TagReference)(panelControl2.Controls[i])).Index;
                    ((TagReference)(panelControl2.Controls[i])).Reload(tagblock[comboBox1.SelectedIndex][Field].GetValue());
                }
                else if (panelControl2.Controls[i].GetType() == typeof(TagBlock))
                {
                    Field = ((TagBlock)(panelControl2.Controls[i])).Index;
                    ((TagBlock)(panelControl2.Controls[i])).Reload(tagblock[comboBox1.SelectedIndex][Field]);
                }
            }
        }

        void SaveValues(int Index)
        {
            int Field = 0;
            for (int i = 0; i < panelControl2.Controls.Count; i++)
            {
                if (panelControl2.Controls[i].GetType() == typeof(Value))
                {
                    Field = ((Value)(panelControl2.Controls[i])).Index;
                    tagblock[Index][Field].SetValue(((Value)(panelControl2.Controls[i])).Save());
                }
                else if (panelControl2.Controls[i].GetType() == typeof(String))
                {
                    Field = ((String)(panelControl2.Controls[i])).Index;
                    tagblock[Index][Field].SetValue(((String)(panelControl2.Controls[i])).Save());
                }
                else if (panelControl2.Controls[i].GetType() == typeof(Enum))
                {
                    Field = ((Enum)(panelControl2.Controls[i])).Index;
                    tagblock[Index][Field].SetValue(((Enum)(panelControl2.Controls[i])).Save());
                }
                else if (panelControl2.Controls[i].GetType() == typeof(Bitmask))
                {
                    Field = ((Bitmask)(panelControl2.Controls[i])).Index;
                    tagblock[Index][Field].SetValue(((Bitmask)(panelControl2.Controls[i])).Save());
                }
                else if (panelControl2.Controls[i].GetType() == typeof(TagReference))
                {
                    Field = ((TagReference)(panelControl2.Controls[i])).Index;
                    tagblock[Index][Field].SetValue(((TagReference)(panelControl2.Controls[i])).Save());
                }
                else if (panelControl2.Controls[i].GetType() == typeof(TagBlock))
                {
                    Field = ((TagBlock)(panelControl2.Controls[i])).Index;
                    ((TagBlock)(panelControl2.Controls[i])).Save();
                }
            }
        }

        private void btnInsertChunk_Click(object sender, EventArgs e)
        {
            // Get copy data
            CopyStruct copydata = Global.EventHandler.GetCopyData();
            if (copydata.BlockName == tagblock.GetName())
            {
                // Overwrite?
                if (copydata.TagBlockData.GetType() == typeof(HaloPlugins.TagBlock))
                    Reload((HaloPlugins.TagBlock)copydata.TagBlockData);
                else
                {
                    if (MessageBox.Show("Would you like to overwrite this block?", "Overwrite Block", MessageBoxButtons.YesNo) == DialogResult.Yes)
                    {
                        this.tagblock[comboBox1.SelectedIndex] = (IMetaNode[])copydata.TagBlockData;
                        UpdateValues();
                    }
                    else
                    {
                        // Add block
                        this.tagblock.AddBlock();
                        this.tagblock[tagblock.BlockCount - 1] = (IMetaNode[])copydata.TagBlockData;

                        // Update
                        comboBox1.Items.Add((tagblock.BlockCount - 1).ToString());
                        comboBox1.SelectedIndex = tagblock.BlockCount - 1;
                    }
                }
            }
            else
                MessageBox.Show("Source block does not match destination!");
        }

        private void btnCopyChunk_Click(object sender, EventArgs e)
        {
            // Create a new copy struct
            CopyStruct copydata = new CopyStruct();
            copydata.Endian = IO.Endianness.Little;
            copydata.ProjectDirectory = Global.ProjectManager.GetOpenedProject().Directory;
            copydata.BlockName = tagblock.GetName();
            copydata.TagBlockData = tagblock[comboBox1.SelectedIndex];

            // Set data
            Global.EventHandler.SetCopyData(copydata);
        }

        private void btnCopyAllChunks_Click(object sender, EventArgs e)
        {
            // Create a new copy struct
            CopyStruct copydata = new CopyStruct();
            copydata.Endian = IO.Endianness.Little;
            copydata.ProjectDirectory = Global.ProjectManager.GetOpenedProject().Directory;
            copydata.BlockName = tagblock.GetName();
            copydata.TagBlockData = tagblock;

            // Set data
            Global.EventHandler.SetCopyData(copydata);
        }
    }
}
