using System;
using System.Drawing;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace Mix.Tool.ArchiveEditor
{
    public partial class MainForm : Form
    {
        #region Native

        private const int LVM_FIRST = 0x1000;
        private const int LVM_SETEXTENDEDLISTVIEWSTYLE = (LVM_FIRST + 54);
        private const int LVM_GETEXTENDEDLISTVIEWSTYLE = (LVM_FIRST + 55);
        private const int LVS_EX_DOUBLEBUFFER = 0x00010000;
        
        [ComVisibleAttribute(false)]
        private class Native
        {
            [DllImport("user32.dll")]
            public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, IntPtr lParam);
        }

        #endregion

        #region Private Value

        private string defCaption = "";
        private Project project = new Project();

        #endregion

        public MainForm()
        {
            InitializeComponent();
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            int styles;

            //リストビューのダブルバッファリング
            styles = (int)Native.SendMessage(listView.Handle, (int)LVM_GETEXTENDEDLISTVIEWSTYLE, 0, (IntPtr)0);
            styles |= LVS_EX_DOUBLEBUFFER;
            Native.SendMessage(listView.Handle, (int)LVM_SETEXTENDEDLISTVIEWSTYLE, 0, (IntPtr)styles);

            //デフォルトのキャプション
            defCaption = this.Text;

            //更新
            UpdateCaption();
            UpdateMenu();
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (CloseProject() == false)
            {
                e.Cancel = true;
            }
        }

        private void mainMenu_File_New_Click(object sender, EventArgs e)
        {
            if (CloseProject() == true)
            {
                using (NewProjectForm form = new NewProjectForm())
                {
                    form.StartPosition = FormStartPosition.CenterParent;

                    if (form.ShowDialog() == DialogResult.OK)
                    {
                        try
                        {
                            project.New(form.RootDirectoryName, form.ArchiveDirectoryName, form.ArchiveFileName);

                            UpdateTreeView(null, project.RootDirectoryNode);
                            UpdateListView(treeView.Nodes[0], project.RootDirectoryNode);
                            UpdateCaption();
                            UpdateMenu();
                        }
                        catch (Exception nfe)
                        {
                            MessageDialog.Show(nfe.Message, Properties.Resources.Title, MessageDialogButtons.OK, MessageDialogIcon.Error);
                        }
                    }
                }
            }
        }

        private void mainMenu_File_Open_Click(object sender, EventArgs e)
        {
            if (CloseProject() == true)
            {
                if (loadProjectDialog.ShowDialog() == DialogResult.OK)
                {
                    try
                    {
                        project.Load(loadProjectDialog.FileName);

                        UpdateTreeView(null, project.RootDirectoryNode);
                        UpdateListView(treeView.Nodes[0], project.RootDirectoryNode);
                        UpdateCaption();
                        UpdateMenu();
                    }
                    catch (Exception lfe)
                    {
                        MessageDialog.Show(lfe.Message, Properties.Resources.Title, MessageDialogButtons.OK, MessageDialogIcon.Error);
                    }
                }
            }
        }

        private void mainMenu_File_Save_Click(object sender, EventArgs e)
        {
            bool success = true;

            if (project.FileName.Length > 0)
            {
                if (project.Save() == false)
                {
                    success = false;
                }
            }
            else
            {
                if (saveProjectDialog.ShowDialog() == DialogResult.OK)
                {
                    success = project.SaveAs(saveProjectDialog.FileName);
                }
            }

            if (success == false)
            {
                MessageDialog.Show(Properties.Resources.Mes_SaveProjectFailed, Properties.Resources.Title, MessageDialogButtons.OK, MessageDialogIcon.Error);
            }
        }

        private void mainMenu_File_SaveAsProject_Click(object sender, EventArgs e)
        {
            if (saveProjectDialog.ShowDialog() == DialogResult.OK)
            {
                if (project.SaveAs(saveProjectDialog.FileName) == false)
                {
                    MessageDialog.Show(Properties.Resources.Mes_SaveProjectFailed, Properties.Resources.Title, MessageDialogButtons.OK, MessageDialogIcon.Error);
                }
            }
        }

        private void mainMenu_File_Property_Click(object sender, EventArgs e)
        {
            using (ProjectPropertyForm form = new ProjectPropertyForm())
            {
                form.RootDirectoryName = project.RootDirectoryName;
                form.ArchiveDirectoryName = project.InputDirectoryName;
                form.ArchiveFileName = project.OutputFileName;
                form.ArchiveAlignment = project.Alignment;

                form.StartPosition = FormStartPosition.CenterParent;

                if (form.ShowDialog() == DialogResult.OK)
                {
                    project.OutputFileName = form.ArchiveFileName;
                    project.Alignment = form.ArchiveAlignment;
                }
            }
        }

        private void mainMenu_File_Export_Click(object sender, EventArgs e)
        {
            using (ExportForm exportForm = new ExportForm(project))
            {
                exportForm.StartPosition = FormStartPosition.CenterParent;
                exportForm.ShowDialog();
            }
        }

        private void mainMenu_File_Exit_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void mainMenu_Help_About_Click(object sender, EventArgs e)
        {
            using (AboutForm aboutForm = new AboutForm())
            {
                aboutForm.StartPosition = FormStartPosition.CenterParent;
                aboutForm.ShowDialog();
            }
        }

        private void treeView_AfterCollapse(object sender, TreeViewEventArgs e)
        {
            e.Node.ImageKey = "DirClose";
            e.Node.SelectedImageKey = "DirClose";
            e.Node.StateImageKey = "DirClose";
        }

        private void treeView_AfterExpand(object sender, TreeViewEventArgs e)
        {
            e.Node.ImageKey = "DirOpen";
            e.Node.SelectedImageKey = "DirOpen";
            e.Node.StateImageKey = "DirOpen";
        }

        private void treeView_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            UpdateListView(e.Node, e.Node.Tag as IDirectoryNode);
        }

        private void listView_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            ListView.SelectedListViewItemCollection selectedItems = listView.SelectedItems;
            if (selectedItems.Count > 0)
            {
                ListViewItem item = selectedItems[0];
                if (item.Tag is TreeNode)
                {
                    TreeNode treeNode;

                    treeNode = item.Tag as TreeNode;
                    treeNode.Expand();

                    UpdateListView(treeNode, treeNode.Tag as IDirectoryNode);
                }
                else if (item.Tag is IFileNode)
                {
                    IFileNode fileNode = item.Tag as IFileNode;
                    Process.Start(fileNode.FullPath);
                }
            }
        }

        private void listView_SelectedIndexChanged(object sender, EventArgs e)
        {
            ListView.SelectedListViewItemCollection selectedItems = listView.SelectedItems;
            if (selectedItems.Count > 0)
            {
                ListViewItem item = selectedItems[0];
                if (item.Tag is TreeNode)
                {
                    TreeNode treeNode;

                    treeNode = item.Tag as TreeNode;
                    treeView.SelectedNode = treeNode;
                }
            }
        }

        protected override void WndProc(ref Message m)
        {
            Mix.Tool.Logger.WndProc(m);

            base.WndProc(ref m);
        }

        private bool CloseProject()
        {
            bool ret = true;

            if (project.Update == true)
            {
                DialogResult dlgResult = MessageDialog.Show(String.Format(Properties.Resources.Mes_SaveProject, project.Name), Properties.Resources.Title, MessageDialogButtons.YesNoCancel, MessageDialogIcon.Warning);

                if (project.FileName.Length > 0)
                {
                    switch (dlgResult)
                    {
                        case DialogResult.Yes:
                            if (project.Save() == false)
                            {
                                ret = false;
                            }
                            break;

                        case DialogResult.Cancel:
                            ret = false;
                            break;
                    }
                }
                else
                {
                    switch (dlgResult)
                    {
                        case DialogResult.Yes:
                            if (saveProjectDialog.ShowDialog() == DialogResult.OK)
                            {
                                if (project.SaveAs(saveProjectDialog.FileName) == false)
                                {
                                    ret = false;
                                }
                            }
                            else
                            {
                                ret = false;
                            }
                            break;

                        case DialogResult.Cancel:
                            ret = false;
                            break;
                    }
                }
            }

            return ret;
        }

        private void UpdateTreeView(TreeNode parentTreeNode, IDirectoryNode dirNode)
        {
            TreeNode treeNode = new TreeNode();

            treeNode.Text = dirNode.Name;
            treeNode.ImageKey = "DirClose";
            treeNode.SelectedImageKey = "DirClose";
            treeNode.StateImageKey = "DirClose";
            treeNode.Tag = dirNode;

            if (parentTreeNode != null)
            {
                parentTreeNode.Nodes.Add(treeNode);
            }
            else
            {
                treeView.Nodes.Clear();
                treeView.Nodes.Add(treeNode);
                treeView.SelectedNode = treeNode;
            }

            foreach (IDirectoryNode child in dirNode.Children)
            {
                UpdateTreeView(treeNode, child);
            }
        }

        private void UpdateListView(TreeNode treeNode, IDirectoryNode dirNode)
        {
            listView.Items.Clear();
            imageList_listView.Images.Clear();

            ////////////////////////////////////////////////////////////////////////////////////////////////////
            // ディレクトリ
            ////////////////////////////////////////////////////////////////////////////////////////////////////

            if (dirNode.Children.Count > 0)
            {
                //ディレクトリが存在していた場合は、ディレクトリのアイコンを事前に0番へ登録しておく
                imageList_listView.Images.Add(Utility.GetFileIcon(dirNode.Children[0].FullPath, Utility.IconType.Small));
            }

            foreach (IDirectoryNode childDirNode in dirNode.Children)
            {
                ListViewItem item = new ListViewItem();

                item.Text = childDirNode.Name;
                item.SubItems.Add("");
                item.SubItems.Add(Utility.GetFileType(childDirNode.FullPath));
                item.SubItems.Add(childDirNode.UpdateDate.ToString());
                item.ImageIndex = 0;

                foreach (TreeNode childTreeNode in treeNode.Nodes)
                {
                    if (childTreeNode.Text == childDirNode.Name)
                    {
                        item.Tag = childTreeNode;
                        break;
                    }
                }

                listView.Items.Add(item);
            }

            ////////////////////////////////////////////////////////////////////////////////////////////////////
            // ファイル
            ////////////////////////////////////////////////////////////////////////////////////////////////////

            foreach (IFileNode childFileNode in dirNode.FileNodes)
            {
                ListViewItem item = new ListViewItem();

                //ファイルのアイコンはファイル単位で登録しておく
                imageList_listView.Images.Add(childFileNode.Name, Utility.GetFileIcon(childFileNode.FullPath, Utility.IconType.Small));

                item.Text = childFileNode.Name;
                item.SubItems.Add(Utility.FileSizeToString( childFileNode.Size));
                item.SubItems.Add(Utility.GetFileType(childFileNode.FullPath));
                item.SubItems.Add(childFileNode.UpdateDate.ToString());
                item.ImageKey = childFileNode.Name;
                item.Tag = childFileNode;

                listView.Items.Add(item);
            }
        }

        private void UpdateCaption()
        {
            if (project.Name.Length > 0)
            {
                this.Text = String.Format("{0} - {1}", project.Name, defCaption);
            }
            else
            {
                this.Text = defCaption;
            }
        }

        private void UpdateMenu()
        {
            bool menuEnabled = (project.RootDirectoryNode != null);

            mainMenu_File_Save.Enabled = menuEnabled;
            mainMenu_File_SaveAs.Enabled = menuEnabled;
            mainMenu_File_Property.Enabled = menuEnabled;
            mainMenu_File_Export.Enabled = menuEnabled;
        }
    }
}
