using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DevExpress.XtraEditors;
using DevExpress.XtraTab;
using System.Windows.Forms;
using System.Drawing;
using System.Diagnostics;
using HaloPlugins;
using IO;
using System.IO;
using Global;

namespace HaloControls
{
    public class TagEditorPage : XtraTabPage
    {
        private bool saved = true;
        /// <summary>
        /// Gets the Saved Status of the Tab
        /// </summary>
        public bool Saved { get { return saved; } }

        private TagDefinition plugin;
        /// <summary>
        /// Gets the Plugin the Tab is using
        /// </summary>
        public TagDefinition Plugin { get { return plugin; } }

        private string path = "";
        /// <summary>
        /// Gets the Location of the Tag
        /// </summary>
        public string Path { get { return path; } }

        public TagEditorPage()
        {
            //Suspend Layout
            this.SuspendLayout();

            // Set Fields
            saved = false;

            // Create Panel
            Panel panel = new Panel();
            panel.SuspendLayout();
            panel.Dock = DockStyle.Fill;
            panel.AutoScroll = true;
            panel.AutoSize = true;
            panel.BackColor = Color.FromKnownColor(KnownColor.Control);
            panel.ResumeLayout();
            this.Controls.Add(panel);

            //Resume
            this.ResumeLayout();
        }

        public TagEditorPage(string Class)
        {
            //Suspend Layout
            this.SuspendLayout();

            // Set Fields
            saved = false;

            // Load tagdef
            plugin = EngineManager.GetEngine()[ProjectManager.GetOpenedProject().Engine].CreateInstance(Class);

            // Create Panel
            Panel panel = new Panel();
            panel.SuspendLayout();
            panel.Dock = DockStyle.Fill;
            panel.AutoScroll = true;
            panel.AutoSize = true;
            panel.BackColor = Color.FromKnownColor(KnownColor.Control);

            // Load into panel
            LoadIntoPanel();

            // Update Tab
            this.Text = "New_Tag." + plugin.CompiledClass + "*";
            panel.ResumeLayout();
            this.Controls.Add(panel);

            //Resume
            this.ResumeLayout();
        }

        public void Open(string Location)
        {
            // Open the tag
            this.path = Location;
            EndianReader br = new EndianReader(Endianness.Little, new FileStream(Location, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite));

            // Create tag def
            string Ext = Location.Substring(Location.LastIndexOf(".") + 1);
            plugin = EngineManager.GetEngine()[ProjectManager.GetOpenedProject().Engine].CreateInstance(Ext);

            // Read
            plugin.Read(br);

            // Close
            br.Close();

            // Suspend Layout
            this.SuspendLayout();

            // Load into panel
            LoadIntoPanel();

            //Resume
            this.Text = Location.Substring(Location.LastIndexOf("\\") + 1);
            this.ResumeLayout();
        }

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

        public void Save()
        {
            //// Double Check Path
            //if (!File.Exists(path))
            //{
            //    SaveFileDialog sfd = new SaveFileDialog();
            //    sfd.Filter = "Halo 2 Tags (*." + TagClass + "|*." + TagClass;
            //    if (sfd.ShowDialog() == DialogResult.OK)
            //    {
            //        path = sfd.FileName;
            //        Globals.Tags.Add(path);
            //    }
            //}

            // Get new values
            int Field = 0;
            for (int i = 0; i < this.Controls[0].Controls.Count; i++)
            {
                if (this.Controls[0].Controls[i].GetType() == typeof(Value))
                {
                    Field = ((Value)this.Controls[0].Controls[i]).Index;
                    plugin[Field].SetValue(((Value)this.Controls[0].Controls[i]).Save());
                }
                else if (this.Controls[0].Controls[i].GetType() == typeof(Enum))
                {
                    Field = ((Enum)this.Controls[0].Controls[i]).Index;
                    plugin[Field].SetValue(((Enum)this.Controls[0].Controls[i]).Save());
                }
                else if (this.Controls[0].Controls[i].GetType() == typeof(Bitmask))
                {
                    Field = ((Bitmask)this.Controls[0].Controls[i]).Index;
                    plugin[Field].SetValue(((Bitmask)this.Controls[0].Controls[i]).Save());
                }
                else if (this.Controls[0].Controls[i].GetType() == typeof(HaloControls.String))
                {
                    Field = ((HaloControls.String)this.Controls[0].Controls[i]).Index;
                    plugin[Field].SetValue(((HaloControls.String)this.Controls[0].Controls[i]).Save());
                }
                else if (this.Controls[0].Controls[i].GetType() == typeof(TagReference))
                {
                    Field = ((HaloControls.TagReference)this.Controls[0].Controls[i]).Index;
                    plugin[Field].SetValue(((HaloControls.TagReference)this.Controls[0].Controls[i]).Save());
                }
                else if (this.Controls[0].Controls[i].GetType() == typeof(TagBlock))
                {
                    Field = ((TagBlock)this.Controls[0].Controls[i]).Index;
                    ((TagBlock)this.Controls[0].Controls[i]).Save();
                }
            }

            // Delete the file
            File.Delete(Path);

            // Reopen stream
            EndianWriter bw = new EndianWriter(Endianness.Little, new FileStream(Path, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite));

            // Write to tag
            plugin.Write(bw);

            // Close
            bw.Close();

            // Done
            MessageBox.Show("Done!");
        }

        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
        }
    }
}
