using System;
using System.IO;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
using System.IO.Compression;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters.Binary;
using System.Linq;

namespace Truffles
{
    public partial class frmMain : Form
    {
        SearchForm searchFrm;

        public frmMain()
        {
            InitializeComponent();
        }

        void checkForParams()
        {
            string[] args = Environment.GetCommandLineArgs();
            foreach (var file in args)
            {
                if(file.EndsWith(".shn"))
                    InitFile(file);
            }
        }

        private void frmMain_Load(object sender, EventArgs e)
        {
            checkForParams();
        }

        void InitFile(string Filename)
        {
            if (!File.Exists(Filename)) return;
            if (Path.GetFileName(Filename) == "QuestData.shn")
            {
                MessageBox.Show("Please use iQuest - this application cannot view this file.");
                return;
            }
            if (!(Filename.ToLower().EndsWith(".shn")))
            {
                SHNFile file = new SHNFile();
                file.LoadMe(Filename);
                OPToolEditor editor = new OPToolEditor(this, file.data, Path.GetExtension(Filename));
                editor.ShowDialog();
                return;
            }
            try
            {
                SHNFile ifile = new SHNFile(Filename);
                TabPage page = new TabPage(Path.GetFileName(Filename));
                FileTabs.TabPages.Add(page);
                DataGridView grid = new DataGridView();
                page.Tag = grid;
                grid.Tag = ifile;

                grid.DataSource = ifile.table;
                grid.AllowUserToDeleteRows = true;
                grid.AllowUserToOrderColumns = true;
                grid.AllowUserToResizeColumns = true;

                grid.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
                grid.Location = new Point(6, 19);
                grid.Name = "grid";
                grid.Size = new System.Drawing.Size(749, 470);
                grid.ScrollBars = ScrollBars.Both;
                grid.TabIndex = 1;
                grid.Dock = DockStyle.Fill;
                grid.DoubleBuffered(true);
                grid.UserDeletedRow += grid_UserDeletedRow;
                grid.SelectionMode = DataGridViewSelectionMode.CellSelect;
                
                page.Controls.Add(grid);
                page.ToolTipText = Filename;
                this.Text = "Truffles™ SHN Editor - " + FileTabs.TabCount.ToString() + " Files Open";
                FileTabs.SelectedTab = page;
                Columns.Text = "Columns: " + file.table.Columns.Count;
                Rows.Text = "Rows: " + file.table.Rows.Count;
            }
            catch (Exception e)
            {
                SQLStatus.Text = e.Message;
            }
        }

        private void grid_UserDeletedRow(object sender, DataGridViewRowEventArgs e)
        {
            Rows.Text = "Rows: " + file.table.Rows.Count;
        }

        public SHNFile file
        {
            get
            {
                try
                {
                    return (SHNFile)dataGrid.Tag;
                }
                catch { MessageBox.Show("No file found");  return null; }
            }
            set
            {
                try
                {
                    dataGrid.Tag = value;
                }
                catch { }
            }
        }

        public DataGridView dataGrid
        {
            get
            {
                return (DataGridView)FileTabs.SelectedTab.Tag;
            }
            set
            {
                FileTabs.SelectedTab.Tag = value;
            }
        }

        void LoadFile()
        {
            OpenFileDialog x = new OpenFileDialog();
            x.Filter = "SHN File (*.shn)|*.shn|Other File(*.*)|*.*";
            x.Title = "Select SHN File";
            if (x.ShowDialog() == DialogResult.OK)
            {
                InitFile(x.FileName);
            }
        }

        private void dataGrid_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
        {
            MessageBox.Show("Data Type: " + ((DataTable)dataGrid.DataSource).Columns[e.ColumnIndex].DataType.Name);
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            LoadFile();
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (file == null) return;
            SaveTo(file.Path);
        }

        void SaveTo(string FileName)
        {
            file.table.DefaultView.RowFilter = null;

            if (File.Exists(FileName))
            {
                File.Delete(FileName);
            }
            for (int i = 0; i < dataGrid.Columns.Count; i++)
            {
                file.displayToReal.Add(dataGrid.Columns[i].DisplayIndex, i);
            }
            bool suc = file.Save(FileName);
            file.displayToReal.Clear();
            if (!suc)
            {
                File.Delete(FileName);
                MessageBox.Show("Could not save file.");
            }
            else
                SQLStatus.Text = "File saved -> " + Path.GetFileName(FileName) + "!";
            file.displayToReal.Clear();
            dataGrid.DataSource = file.table;
        }

        private void copySelectedRowToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MemoryStream stream = new MemoryStream();
            BinaryWriter writor = new BinaryWriter(stream);
            if (file == null) return;
            DataTable toCopyTo = new DataTable();
            toCopyTo = file.table.Clone();
            writor.Write((int)dataGrid.SelectedRows.Count);
            foreach (DataGridViewRow row in dataGrid.SelectedRows.Cast<DataGridViewRow>().OrderBy(row1 => row1.Index))
            {
                DataRow myRow = (row.DataBoundItem as DataRowView).Row;
                object[] EachColumn = myRow.ItemArray;
                writor.Write((int)EachColumn.Length);
                for (int i = 0; i < EachColumn.Length; i++)
                {
                    writor.Write(file.table.Columns[i].ColumnName);
                    writor.Write(EachColumn[i].ToString());
                }
                writor.Write((byte)0x00);
            }
            stream.Position = 0;
            byte[] toCop = new byte[stream.Length];
            stream.Read(toCop, 0, (int)stream.Length);
            Clipboard.SetData("Bytes", toCop);
            writor.Close();
            SQLStatus.Text = "Copied to clipboard.";
        }

        private string Serialize(object objectToSerialize)
        {
            string serialString = null;
            using (System.IO.MemoryStream ms1 = new System.IO.MemoryStream())
            {
                BinaryFormatter b = new BinaryFormatter();
                b.Serialize(ms1, objectToSerialize);
                byte[] arrayByte = ms1.ToArray();
                serialString = Convert.ToBase64String(arrayByte);
            }
            return serialString;
        }

        private object DeSerialize(string serializationString)
        {
            object deserialObject = null;
            byte[] arrayByte = Convert.FromBase64String(serializationString);
            using (System.IO.MemoryStream ms1 = new System.IO.MemoryStream(arrayByte))
            {
                BinaryFormatter b = new BinaryFormatter();
                deserialObject = b.Deserialize(ms1);
            }
            return deserialObject;
        }

        private void searchToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (FileTabs.TabPages.Count < 1) return;
            if (searchFrm == null ) 
                searchFrm = new SearchForm(this);
           searchFrm.Text = "Search: " + FileTabs.SelectedTab.Text;
           searchFrm.Init();
           searchFrm.Show();
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            About lol = new About();
            lol.ShowDialog();
        }

        private void renameToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (dataGrid.DataSource == null) return;
            RenameBox box = new RenameBox(this);
            box.init();
            box.ShowDialog();    
        }

        private void deleteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (dataGrid.DataSource == null) return;
            DeleteColumn deleter = new DeleteColumn(this);
            deleter.init();
            deleter.ShowDialog();
            Columns.Text = "Columns: " + file.table.Columns.Count;
        }

        private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            Application.Exit();
        }

        private void createToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (dataGrid.DataSource == null)
            {
                MessageBox.Show("Please open a file first");
                return;
            }
            CreateColumn colcreate = new CreateColumn(this);
            colcreate.init();
            colcreate.ShowDialog();
            Columns.Text = "Columns: " + file.table.Columns.Count;
        }

        private void deleteRowsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (dataGrid.DataSource == null) return;
            MessageBox.Show("Please select the rows & press delete");
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        public void BigTabs(TabPage page)
        {
            page.Width += 290;
            ((DataGridView)page.Tag).Width += 290;
        }

        public void SmallTabs(TabPage page)
        {
            page.Width -= 290;
            ((DataGridView)page.Tag).Width -= 290;
        }

        private void expRateEditorToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (file == null) return;
            if (!file.Path.EndsWith("MobInfoServer.shn"))
            {
                MessageBox.Show("Please open MobInfoServer.shn first!");
                return;
            }     
            ExpEditor editor = new ExpEditor(this);
            editor.ShowDialog();
        }

        private void oDTEditorToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OPToolEditor editor = new OPToolEditor(this, new byte[1], ".dat");
            editor.ShowDialog();
        }

        private void translatorToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.file == null) return;
            Translator trans = new Translator(this);
            trans.ShowDialog();
        }

        private void columnMultiplierToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.file == null) return;
            ColMultiplier mult = new ColMultiplier(this);
            mult.ShowDialog();
        }

        private void columnAutosetToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ColAutoSet setter = new ColAutoSet(this);
            setter.ShowDialog();
        }

        private void debugToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DebugFrm debuggor = new DebugFrm(this);
            debuggor.ShowDialog();
        }

        private void itemEditorToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (file == null) { MessageBox.Show("Please open ItemInfo.shn first!"); return; }
            ItemEditor editor = new ItemEditor(this);
            editor.ShowDialog();
        }

        private void specOutputToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (file == null) return;
            moveColumn mover = new moveColumn(this);
            mover.ShowDialog();
        }

        private void shopCreatorToolStripMenuItem_Click(object sender, EventArgs e)
        {
            createShop creator = new createShop();
            creator.ShowDialog();
        }

        private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveFileDialog diag = new SaveFileDialog();
            diag.FileName = Path.GetFileName(file.Path);
            diag.Filter = "SHN File (*.shn)|*.shn";
            if (diag.ShowDialog() == DialogResult.OK)
            {
                SaveTo(diag.FileName);
            }
        }

        private void headerInfoToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.file == null) return;
            frmEditFileProps props = new frmEditFileProps(this);
            props.ShowDialog();
        }

        private void newToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SHNFile ifile = new SHNFile();
            ifile.CreateDefaultLayout();

            #region tabshit
            TabPage page = new TabPage("New File.shn");
            FileTabs.TabPages.Add(page);
            FileTabs.SelectedTab = page;
            DataGridView grid = new DataGridView();
            page.Tag = grid;
            grid.Tag = ifile;

            grid.DataSource = ifile.table;
            grid.AllowUserToDeleteRows = true;
            grid.AllowUserToOrderColumns = true;
            grid.AllowUserToResizeColumns = true;

            grid.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
            grid.Location = new System.Drawing.Point(6, 19);
            grid.Name = "grid";
            grid.Size = new System.Drawing.Size(749, 470);
            grid.ScrollBars = ScrollBars.Both;
            grid.TabIndex = 1;

            page.Controls.Add(grid);
            page.ToolTipText = "New File";
            this.Text = "Truffles SHN Editor - " + FileTabs.TabCount.ToString() + " files open";
            #endregion
        }

        private void columnCompareEditToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (FileTabs.TabCount == 0)
            {
                MessageBox.Show("No shn files are open!");
                return;
            }
            colMassEdit massEdit = new colMassEdit(this);
            massEdit.Show();
        }

        private void frmMain_DragDrop(object sender, DragEventArgs e)
        {
            string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
            foreach (string file in files)
            {
                if (Path.GetExtension(file).ToLower() != ".shn") return;
                InitFile(file);
            }
        }

        private void frmMain_DragOver(object sender, DragEventArgs e)
        {
            e.Effect = DragDropEffects.All;
        }

        private void FileTabs_SelectedIndexChanged(object sender, EventArgs e)
        {
            Columns.Text = "Columns: " + file.table.Columns.Count;
            Rows.Text = "Rows: " + file.table.Rows.Count;
        }

        private void columnReOrderToolStripMenuItem_Click(object sender, EventArgs e)
        {
            IDReorder Reorder = new IDReorder(this);
            Reorder.Show();
        }

        private void OnRightTab(TabPage pPage, Point position)
        {
            ContextMenu menu = new ContextMenu();
            menu.MenuItems.Add("Rest Filter", TabRight_Filter_Click).Tag = pPage;
            menu.MenuItems.Add("Save", TabRight_Save_Click).Tag = pPage;
            menu.MenuItems.Add("Close", TabRight_Close_Click).Tag = pPage;
            menu.Show(pPage, position);
        }

        private void TabRight_Close_Click(object sender, EventArgs e)
        {
            if (FileTabs.TabCount == 0) return;
            file.Dispose();
            file = null;
            FileTabs.TabPages.Remove(FileTabs.SelectedTab);
            SQLStatus.Text = "Closed Tab.";
            this.Text = "Truffles™ SHN Editor - " + FileTabs.TabCount.ToString() + " Files Open";
        }

        private void TabRight_Save_Click(object sender, EventArgs e)
        {
            SaveTo(file.Path);
        }

        private void TabRight_Filter_Click(object sender, EventArgs e)
        {
            file.table.DefaultView.RowFilter = null;
            SQLStatus.Text = "Filter Rest ->" + Path.GetFileName(file.Path) + "!";
        }

        private void FileTabs_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                for (int i = 0; i < FileTabs.TabCount; i++)
                {
                    Rectangle r = FileTabs.GetTabRect(i);
                    if (r.Contains(e.Location))
                    {
                        TabPage page = FileTabs.TabPages[i];
                        if (FileTabs.SelectedTab != page)
                            FileTabs.SelectedTab = page;
                        OnRightTab(page, new Point(e.X, e.Y - 20));
                    }
                }
            }
        }

        private void columnRenameToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ColReplace replace = new ColReplace(this);
            replace.Show();
        }

        private void pasteRowToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (Clipboard.ContainsData("Bytes"))
            {
                byte[] array = (byte[])Clipboard.GetData("Bytes");
                BinaryReader reader = new BinaryReader(new MemoryStream(array));
                int rowCount = reader.ReadInt32();
                for (int i = 0; i < rowCount; i++)
                {
                    int columnCount = reader.ReadInt32();
                    Dictionary<string, string> clipCols = new Dictionary<string, string>();
                    byte test = 1;
                    for (int iz = 0; iz < columnCount; iz++)
                    {
                        string colName = reader.ReadString();
                        string colContent = reader.ReadString();
                        clipCols.Add(colName, colContent);
                    }
                    test = reader.ReadByte();
                    if (test != 0x00) return;
                    //allright, now they're all in the array
                    DataRow row = file.table.NewRow();
                    for (int iw = 0; iw < file.table.Columns.Count; iw++)
                    {
                        string internalName = file.table.Columns[iw].ColumnName;
                        if (clipCols.ContainsKey(internalName))
                            row[iw] = clipCols[internalName];
                    }
                    file.table.Rows.Add(row);
                }
                reader.Close();
                SQLStatus.Text = "Imported " + rowCount.ToString() + " rows.";
                Rows.Text = "Rows: " + file.table.Rows.Count;
            }
            else
                SQLStatus.Text = "Clipboard has wrong type of data.";
        }

        private void columnFilterToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ColumnFilter filter = new ColumnFilter(this);
            filter.ShowDialog();
        }

        private void copyPasteSelectedToolStripMenuItem_Click(object sender, EventArgs e)
        {
                List<DataGridViewRow> new_list = new List<DataGridViewRow>();

                for(int i = 0; i < dataGrid.SelectedRows.Count; i++)
                {
                    new_list.Add(dataGrid.SelectedRows[i]);
                }

                new_list.Reverse();

                foreach (var row in new_list)
                {
                    file.table.ImportRow(file.table.Rows[row.Index]);
                }
        }
    }
}
