using FizzyLauncher.Models;
using RyzStudio.Windows.Forms;
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using AppResource = FizzyLauncher.AppResource;

namespace FizzyLauncher.Windows.Forms
{
    public partial class TilePanel : TUserControl
    {
        protected bool isDragging = false;
        protected Point startPosition = new Point();

        protected int imageLeft = 0;
        protected int imageTop = 11;
        protected int labelMargin = 3;
        protected int labelTop = 47;
        protected Rectangle labelRectangle = new Rectangle();

        protected string title = "";
        protected Image icon = null;
        protected ContextMenuStrip groupContextMenu = null;
        protected TileModel modelInfo = new TileModel();


        public TilePanel() : base()
        {
            InitializeComponent();

            this.AllowDrop = true;
            this.AutoSize = false;
            this.BackColor = Color.FromArgb(250, 250, 250);
            this.ContextMenuStrip = contextMenuStrip1;
            this.DoubleBuffered = true;
            this.Font = new Font(this.Font.FontFamily, 8.25F);
            this.ForeColor = Color.FromArgb(99, 105, 119);
            this.Size = new Size(70, 70);
            this.MaximumSize = this.MinimumSize = this.Size;
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            this.AllowDrop = true;
            this.AutoSize = false;
            this.BackColor = Color.FromArgb(250, 250, 250);
            this.ContextMenuStrip = contextMenuStrip1;
            this.DoubleBuffered = true;
            this.Font = new Font(this.Font.FontFamily, 8.25F);
            this.Size = new Size(70, 70);
            this.MaximumSize = this.MinimumSize = this.Size;
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            Graphics g = e.Graphics;


            if (this.Image != null)
            {
                g.DrawImage(this.Image, new Point(imageLeft, imageTop));
            }

            if (!string.IsNullOrWhiteSpace(this.Title))
            {
                TextRenderer.DrawText(e.Graphics, this.Title, this.Font, labelRectangle, this.ForeColor, TextFormatFlags.HorizontalCenter | TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
            }

            g.DrawRectangle(new Pen(Color.FromArgb(204, 206, 218), 1), new Rectangle(this.DisplayRectangle.X, this.DisplayRectangle.Y, (this.DisplayRectangle.Width - 1), (this.DisplayRectangle.Height - 1)));

        }

        [Category("Tile"), Browsable(true)]
        public Image Image
        {
            get => icon;
            protected set
            {
                icon = value;

                if (icon == null)
                {
                    imageLeft = 0;
                }
                else
                {
                    imageLeft = (this.Width - icon.Width) / 2;
                }
            }
        }

        [Category("Tile"), Browsable(true)]
        public string Title
        {
            get => title;
            protected set
            {
                title = value;

                labelRectangle = new Rectangle(labelMargin, labelTop, (this.Width - (labelMargin * 2)), (this.Height - labelTop - 1));

                this.Invalidate();
            }
        }


        [Browsable(false)]
        public TileModel ModelInfo => modelInfo;

        public TilePanelLayout PanelContainer
        {
            get
            {
                if (this.Parent == null)
                {
                    return null;
                }

                if (this.Parent.GetType() != typeof(TilePanelLayout))
                {
                    return null;
                }

                return (TilePanelLayout)this.Parent;
            }
        }

        protected override void OnDragDrop(DragEventArgs e)
        {
            string[] fileList = e.Data.GetData(DataFormats.FileDrop) as string[];

            if (this.ModelInfo.IsGroup)
            {
                this.DropFileList(fileList);

                invalidateGroupMenu(this.ModelInfo);
            }
            else
            {
                if (this.PanelContainer != null)
                {
                    this.PanelContainer.DropFileList(fileList);
                }
            }
        }

        protected override void OnDragOver(DragEventArgs e)
        {
            base.OnDragDrop(e);

            e.Effect = (e.Data.GetDataPresent(DataFormats.FileDrop)) ? DragDropEffects.Link : DragDropEffects.None;
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);

            isDragging = false;
        }

        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);

            TilePanelLayout container = this.PanelContainer;
            if (container == null)
            {
                return;
            }

            this.BringToFront();

            if (((e.Button == MouseButtons.Left) && (Control.ModifierKeys == Keys.Control)) || (e.Button == MouseButtons.Right))
            {
                isDragging = true;
                startPosition = e.Location;
            }
        }

        protected override void OnMouseClick(MouseEventArgs e)
        {
            base.OnMouseClick(e);

            if (Control.ModifierKeys == Keys.Control) return;
            if (this.ModelInfo == null) return;

            if (e.Button == MouseButtons.Left)
            {
                if (this.ModelInfo.IsGroup)
                {
                    if (groupContextMenu != null)
                    {
                        invalidateGroupMenuSize();

                        groupContextMenu.Show(this, e.Location);
                    }
                }
                else
                {
                    OnMouseDoubleClick(e);
                }
            }
        }

        protected override void OnMouseDoubleClick(MouseEventArgs e)
        {
            base.OnMouseDoubleClick(e);

            if (Control.ModifierKeys == Keys.Control) return;

            if (e.Button == MouseButtons.Left)
            {
                execute(this.ModelInfo);
            }
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);

            if (isDragging)
            {
                TilePanelLayout layoutPanel = this.PanelContainer;
                if (layoutPanel == null)
                {
                    return;
                }

                int x = (this.Location.X + (e.Location.X - startPosition.X));
                int y = (this.Location.Y + (e.Location.Y - startPosition.Y));

                layoutPanel.MoveTile(this, x, y);
            }
        }


        public void DropFileList(string[] fileList)
        {
            if (fileList == null)
            {
                return;
            }

            if (fileList.Length <= 0)
            {
                return;
            }

            if (string.IsNullOrWhiteSpace(fileList[0]))
            {
                return;
            }

            TileModel model = new TileModel()
            {
                ProcessFilename = fileList[0],
                Title = Path.GetFileName(fileList[0])
            };

            // exe
            if (Path.GetExtension(fileList[0]).Equals(".exe", StringComparison.CurrentCultureIgnoreCase))
            {
                if (File.Exists(fileList[0]))
                {
                    try
                    {
                        FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(fileList[0]);
                        if (fvi != null)
                        {
                            model.Title = fvi.ProductName;
                        }
                    }
                    catch
                    {
                        // do nothing
                    }
                }

                if (string.IsNullOrWhiteSpace(model.Title))
                {
                    model.Title = Path.GetFileNameWithoutExtension(fileList[0]);
                }
            }

            this.ModelInfo.Items.Add(model);
        }

        public void LoadInfo(TileModel model)
        {
            this.modelInfo = model;

            this.Image = null;
            this.Title = model.Title;

            if (this.modelInfo.IsGroup)
            {
                this.Image = AppResource.folder_32;

                invalidateGroupMenu(this.modelInfo);
            }
            else
            {
                this.Image = getIcon(model);
            }

            toolTip1.SetToolTip(this, this.Title);
        }

        private void editToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.ModelInfo.IsGroup)
            {
                EditTileFolderForm.ShowEditDialog(this);
            }
            else
            {
                EditTileForm.ShowEditDialog(this);
            }
        }

        private void removeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.PanelContainer == null)
            {
                return;
            }

            this.PanelContainer.Remove(this);
        }

        protected void execute(TileModel model)
        {
            if (model == null)
            {
                return;
            }

            if (model.IsGroup)
            {
                return;
            }

            if (string.IsNullOrWhiteSpace(model.CleanProcessFilename))
            {
                return;
            }

            if (!File.Exists(model.CleanProcessFilename))
            {
                return;
            }

            ProcessStartInfo p = new ProcessStartInfo();
            p.FileName = model.CleanProcessFilename;
            p.WindowStyle = model.ProcessWindowStyle;

            if (!string.IsNullOrWhiteSpace(model.CleanProcessArgument))
            {
                p.Arguments = model.CleanProcessArgument;
            }

            if (!string.IsNullOrWhiteSpace(model.CleanProcessWorkingDirectory))
            {
                p.WorkingDirectory = model.CleanProcessWorkingDirectory;
            }

            if (model.ProcessAsAdmin)
            {
                p.UseShellExecute = true;
                p.Verb = "runas";
            }

            MainForm parentForm = findMainForm();
            if (parentForm != null)
            {
                if (parentForm.CurrentSession != null)
                {
                    if (parentForm.CurrentSession.HideOnClick)
                    {
                        parentForm.Visible = false;
                    }
                }
            }

            try
            {
                Process.Start(p);
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.Message);
            }
        }

        protected Image getIcon(TileModel model)
        {
            if (!File.Exists(model.CleanProcessFilename))
            {
                return null;
            }

            try
            {
                return Icon.ExtractAssociatedIcon(model.CleanProcessFilename)?.ToBitmap();
            }
            catch
            {
                // do nothing
            }

            return null;
        }

        protected void invalidateGroupMenu(TileModel model)
        {
            if (groupContextMenu == null)
            {
                groupContextMenu = new ContextMenuStrip();
            }

            groupContextMenu.Items.Clear();

            if (model.Items == null)
            {
                return;
            }

            foreach (TileModel item in model.Items)
            {
                ToolStripItem toolItem = groupContextMenu.Items.Add(item.Title);
                toolItem.Image = getIcon(item);
                toolItem.Tag = item;
                toolItem.Click += toolItem_Click;
            }
        }

        protected void invalidateGroupMenuSize()
        {
            if (this.PanelContainer != null)
            {
                if (this.PanelContainer.MainForm != null)
                {
                    if (this.PanelContainer.MainForm.CurrentSession != null)
                    {
                        if (this.PanelContainer.MainForm.CurrentSession.EnableBigIconInFolder)
                        {
                            groupContextMenu.ImageScalingSize = new Size(24, 24);
                            return;
                        }
                    }
                }
            }

            groupContextMenu.ImageScalingSize = new Size(16, 16);
        }

        protected MainForm findMainForm()
        {
            Control item = this;

            while (true)
            {
                item = item.Parent;
                if (item == null)
                {
                    return null;
                }

                if (item.GetType() == typeof(MainForm))
                {
                    return (item as MainForm);
                }
            }
        }

        private void toolItem_Click(object sender, EventArgs e)
        {
            if (sender.GetType() != typeof(ToolStripMenuItem))
            {
                return;
            }

            ToolStripMenuItem item = (sender as ToolStripMenuItem);
            if (item.Tag == null)
            {
                return;
            }

            if (item.Tag.GetType() != typeof(TileModel))
            {
                return;
            }

            TileModel model = (item.Tag as TileModel);
            execute(model);
        }

    }
}