using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using FizzyLauncher.Models;
using RyzStudio.Windows.Forms;

namespace FizzyLauncher.Windows.Forms
{
    public partial class TilePanelLayout : TileGridPanelLayout<TilePanel>
    {
        protected TileGroupModel groupModel = null;


        public TilePanelLayout(TileGroupModel model) : base()
        {
            InitializeComponent();

            this.TitleContextMenuStrip = contextMenuStrip2;
            this.ContainerContextMenuStrip = contextMenuStrip1;

            this.LoadModel(model);
        }

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

            this.LoadShortcuts(fileList);
        }

        public new bool EnableAnimation
        {
            get
            {
                MainForm mainForm = this.MainForm;
                if (mainForm == null)
                {
                    return false;
                }

                if (mainForm.CurrentSession == null)
                {
                    return false;
                }

                base.EnableAnimation = mainForm.CurrentSession.EnableAnimation;

                return base.EnableAnimation;
            }
            set => base.EnableAnimation = value;
        }

        public void LoadShortcuts(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.AddTile(model);
        }

        public TileGroupModel Model
        {
            get
            {
                TileGroupModel rs = new TileGroupModel()
                {
                    Title = groupModel.Title,
                    GridSize = new Size(this.GridSize.X, this.GridSize.Y),
                    IsExpanded = this.IsExpanded,
                    IsExclusive = groupModel.IsExclusive,
                    Items = this.Tiles
                };

                return rs;
            }
        }


        public MainForm MainForm { get => UIControl.GetParentsUntil<MainForm>(this.Parent); }

        public List<TileModel> Tiles
        {
            get
            {
                List<TileModel> result = new List<TileModel>();
                foreach (GridTileItem item in this.GridTileItems.Where(x => x.Tile.GetType() == typeof(TilePanel)))
                {
                    TileModel model = (item.Tile as TilePanel).ModelInfo;
                    model.Position = item.Coord;

                    result.Add(model);
                }

                return result;
            }
        }

        public void AddTile(TileModel tile)
        {
            Point gridSize = this.GridSize;

            if (GridTileItems.Count >= (gridSize.X * gridSize.Y))
            {
                this.SetGridSize(gridSize.X, (gridSize.Y + 1));
            }

            Point? newCoord = tile.Position;
            if ((newCoord == null) || HasTile(tile.Position))
            {
                newCoord = FindLastFreeCoord();
            }

            if (newCoord == null)
            {
                return;
            }

            tile.Position = newCoord.Value;

            TilePanel panel = new TilePanel();
            panel.LoadInfo(tile);
            panel.Location = ConvertCoordToLocation(tile.Position);

            GridTileItems.Add(new GridTileItem()
            {
                Tile = panel,
                Coord = tile.Position
            });

            this.Controls.Add(panel);
        }

        public void AddGroup()
        {
            if (this.FlowLayoutPanel == null)
            {
                return;
            }

            this.FlowLayoutPanel.Controls.Add(new TilePanelLayout(new TileGroupModel()
            {
                Title = "New Group",
                GridSize = new Size(8, 1)
            }));
        }

        public void AddRow() => this.SetGridSize(this.GridSize.X, (this.GridSize.Y + 1));

        public void EditGroup()
        {
            //EditGroupForm.ShowDialog(this);
        }

        public async void LoadModel(TileGroupModel model)
        {
            groupModel = model;

            this.Title = groupModel?.Title ?? string.Empty;
            this.IsExpanded = groupModel.IsExpanded;

            //label1.Image = (isExpanded ? AppResource.toggle_right_ea_16 : AppResource.toggle_left_ea_16);

            this.SetGridSize(groupModel.GridSize.Width, groupModel.GridSize.Height);
            this.LoadTiles(model.Items);
            this.SetGridSize(groupModel.GridSize.Width, groupModel.GridSize.Height);

            await this.Invalidate();
        }

        public async void UpdateModel(TileGroupModel model)
        {
            groupModel = model;

            this.Title = groupModel?.Title ?? string.Empty;
            this.IsExpanded = groupModel.IsExpanded;

            await this.Invalidate();
        }

        public void LoadTiles(List<TileModel> tiles)
        {
            if (tiles == null)
            {
                return;
            }

            if (tiles.Count() <= 0)
            {
                return;
            }

            foreach (TileModel item in tiles)
            {
                // resolve final grid position
                Point? confirmedPosition = ResolveCoord(item.Position);
                if (confirmedPosition == null)
                {
                    continue;
                }

                // place control
                TilePanel panel = new TilePanel();
                panel.LoadInfo(item);
                panel.Location = ConvertCoordToLocation(confirmedPosition.Value);

                GridTileItems.Add(new GridTileItem()
                {
                    Tile = panel,
                    Coord = confirmedPosition.Value
                });

                this.Controls.Add(panel);
            }
        }

        private void SetGridSize(int width, int height)
        {
            this.GridSize = new Point(width, height);

            groupModel.GridSize = new Size(groupModel.GridSize.Width, height);
        }

        protected override async void label1_MouseClick(object sender, MouseEventArgs e)
        {
            base.label1_MouseClick(sender, e);

            if (isAnimating)
            {
                return;
            }

            if (e.Button == MouseButtons.Left)
            {
                // exclusivity
                if (this.IsExpanded)
                {
                    if (this.Model.IsExclusive)
                    {
                        if (this.FlowLayoutPanel != null)
                        {
                            foreach (TilePanelLayout item in this.FlowLayoutPanel.Controls.OfType<TilePanelLayout>())
                            {
                                if (item.Equals(this))
                                {
                                    continue;
                                }

                                await item.Collapse();
                            }
                        }
                    }
                }
            }
        }

        #region tile context menu

        /// <summary>
        /// Add tile
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void addTileMenuItem_Click(object sender, EventArgs e)
        {
            Point coord = ConvertLocationToCoord(lastMousePosition.X, lastMousePosition.Y);

            //EditTileForm.ShowAddDialog(this, coord);
        }

        /// <summary>
        /// Add folder
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void addListTileMenuItem_Click(object sender, EventArgs e)
        {
            Point coord = ConvertLocationToCoord(lastMousePosition.X, lastMousePosition.Y);

            //EditTileFolderForm.ShowAddDialog(this, coord);
        }

        #endregion

        #region group context menu

        /// <summary>
        /// Add group
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void addGroupMenuItem_Click(object sender, EventArgs e)
        {
            this.AddGroup();
        }

        /// <summary>
        /// Edit group
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void editGroupMenuItem_Click(object sender, EventArgs e)
        {
            this.EditGroup();
        }

        /// <summary>
        /// Add row
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolStripMenuItem5_Click(object sender, EventArgs e)
        {
            this.AddRow();
        }

        /// <summary>
        /// Remove row
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void removeRowToolStripMenuItem_Click_1(object sender, EventArgs e)
        {
            if (this.GridSize.Y <= 1)
            {
                return;
            }

            bool rs = GridTileItems.Exists(x => x.Coord.Y.Equals(this.GridSize.Y - 1));
            if (rs)
            {
                return;
            }

            this.SetGridSize(this.GridSize.X, (this.GridSize.Y - 1));
        }

        /// <summary>
        /// Move to top
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void moveTopMenuItem_Click(object sender, EventArgs e)
        {
            this.MoveTop();
        }

        /// <summary>
        /// Move up
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void moveUpMenuItem_Click(object sender, EventArgs e)
        {
            this.MoveUp();
        }

        /// <summary>
        /// Move down
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void moveDownMenuItem_Click(object sender, EventArgs e)
        {
            this.MoveDown();
        }

        /// <summary>
        /// Move to bottom
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void moveBottomMenuItem_Click(object sender, EventArgs e)
        {
            this.MoveBottom();
        }

        /// <summary>
        /// Remove group
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void removeGroupMenuItem3_Click(object sender, EventArgs e)
        {
            this.Remove();
        }

        #endregion


    }
}
