using System.Drawing.Drawing2D;
using OpenCvSharp;
using OpenCvSharp.Extensions;
using VisionBuilder.UI.Common.Processing;
using Size = System.Drawing.Size;

namespace Hawkeye.VisionBuilder.Features.ImagesStrip
{
    public partial class ImageStripPanel : Form, IImageSource
    {


        public ImageStripPanel()
        {

            InitializeComponent();

            listView1.SelectedIndexChanged += ListView1_SelectedIndexChanged;
        }

        private void ListView1_SelectedIndexChanged(object? sender, EventArgs e)
        {
            if (listView1.SelectedItems.Count > 0)
            {
                lblSelectedImage.Text = $"{listView1.SelectedIndices[0] + 1}/{listView1.Items.Count}";
                var path = (string)listView1.SelectedItems[0].Tag;
                listView1.SelectedItems[0].ImageKey = path;
                var img = new Mat(path);
                var image = new Workflow.Datatypes.HawkeyeImage()
                {
                    Filename = path,
                    ImageData = img
                };
                listView1.LargeImageList.Images.RemoveByKey(path);
                listView1.LargeImageList.Images.Add(path, img.Resize(new OpenCvSharp.Size(108, 108)).ToBitmap());
                ImageSelected(image);
            }
        }

        public bool IsExecutingWorkflow
        {
            get => ckbExecuteWorkflow.Checked;
            set => ckbExecuteWorkflow.Checked = value;
        }

        public event Action<Workflow.Datatypes.HawkeyeImage> ImageSelected = delegate { };
        public void LoadImage(Mat image)
        {
            ImageList imageList = new ImageList();
            imageList.ImageSize = new Size(108, 108);
            listView1.LargeImageList = imageList;
            listView1.Items.Clear();
            imageList.Images.Add("image", image.ToBitmap());
            var item = listView1.Items.Add("image");
            item.Tag = new Workflow.Datatypes.HawkeyeImage()
            {
                Filename = "image",
                ImageData = image
            };
            item.Text = "";
            item.ImageKey = "image";

            listView1.SelectedIndices.Clear();
            listView1.SelectedIndices.Add(0);
        }
        public Bitmap FitImage(Image image, int targetWidth, int targetHeight)
        {
            var aspectRatio = (float)image.Width / image.Height;
            int width;
            int height;
            if ((float)targetWidth / targetHeight > aspectRatio)
            {
                width = (int)(targetHeight * aspectRatio);
                height = targetHeight;
            }
            else
            {
                width = targetWidth;
                height = (int)(targetWidth / aspectRatio);
            }

            Bitmap bitmap = new Bitmap(targetWidth, targetHeight);
            using (Graphics graphics = Graphics.FromImage(bitmap))
            {
                graphics.DrawImage(image, new Rectangle(0, 0, width, height));
                return bitmap;
            }
        }

        public void LoadImages(string directory)
        {
            listView1.BeginUpdate();
            ImageList imageList = new ImageList();
            imageList.ImageSize = new Size(108, 108);
            listView1.LargeImageList = imageList;
            listView1.Items.Clear();
            var mock = new Bitmap(108, 108);
            using (Graphics g = Graphics.FromImage(mock))
            {
                var brush = new HatchBrush(HatchStyle.Percent50, Color.LightGray, Color.Transparent);
                g.FillRectangle(brush, 0, 0, 108, 108);

                g.DrawString("Not loaded", new Font("Arial", 12), Brushes.Gray, new PointF(0, 0));
            }
            var allImages = Directory.GetFiles(directory, "*.bmp", SearchOption.AllDirectories)
                .Concat(Directory.GetFiles(directory, "*.png", SearchOption.AllDirectories))
                .Concat(Directory.GetFiles(directory, "*.jpg", SearchOption.AllDirectories))
                .Where(x => !Path.GetFileNameWithoutExtension(x).Contains("_analysis"))
                //.Select(x=>new {path=x,bmp = new Bitmap(x)})
                .Select(x => new { path = x, bmp = mock })
                .ToArray();


            imageList.Images.Add("none", mock);
            

            foreach (var image in allImages)
            {

                
                var item = listView1.Items.Add(image.path);
                item.Text = "";
                item.Tag = image.path;
                item.ImageKey = "none";
            }

            if (listView1.Items.Count > 0)
            {
                listView1.SelectedIndices.Clear();
                listView1.SelectedIndices.Add(0);
                toolStrip1.Enabled = true;
            }
            else
            {
                toolStrip1.Enabled = false;
            }
            listView1.EndUpdate();
        }

        private void btnToStart_Click(object sender, EventArgs e)
        {
            listView1.SelectedIndices.Clear();
            listView1.SelectedIndices.Add(0);
            listView1.EnsureVisible(listView1.SelectedIndices[0]);
        }

        public void Prev()
        {
            btnPrev_Click(null, null);
        }
        private void btnPrev_Click(object sender, EventArgs e)
        {
            if (listView1.SelectedIndices.Count == 0) return;
            var index = listView1.SelectedIndices[0];
            index--;
            if (index < 0) index++;
            listView1.SelectedIndices.Clear();
            listView1.SelectedIndices.Add(index);
            listView1.EnsureVisible(listView1.SelectedIndices[0]);
        }

        public void Next()
        {
            btnNext_Click(null, null);
        }

        private void btnNext_Click(object sender, EventArgs e)
        {
            
            if (listView1.SelectedIndices.Count == 0) return;
            var index = listView1.SelectedIndices[0];
            index++;
            if (index > listView1.Items.Count - 1) index--;
            listView1.SelectedIndices.Clear();
            listView1.SelectedIndices.Add(index);
            listView1.EnsureVisible(listView1.SelectedIndices[0]);
        }

        private void btnToEnd_Click(object sender, EventArgs e)
        {
            listView1.SelectedIndices.Clear();
            listView1.SelectedIndices.Add(listView1.Items.Count - 1);
            listView1.EnsureVisible(listView1.SelectedIndices[0]);
        }

        private void btnPlay_Click(object sender, EventArgs e)
        {
            Task.Run(Playback);
        }

        private async Task Playback()
        {
            while (btnPlay.Checked)
            {
                Action a = () =>
                {
                    if (listView1.SelectedIndices.Count == 0) return;
                    var index = listView1.SelectedIndices[0];
                    index++;
                    if (index > listView1.Items.Count - 1)
                    {
                        if (cbRepeat.Checked)
                        {
                            index = 0;
                        }
                        else
                        {
                            btnPlay.Checked = false;
                            return;
                        }

                    }
                    listView1.SelectedIndices.Clear();
                    listView1.SelectedIndices.Add(index);
                    listView1.EnsureVisible(listView1.SelectedIndices[0]);
                };
                listView1.Invoke(a);
                await Task.Delay(int.Parse((string)ncInterval.Text));
            }
        }

        public string GetName()
        {
            return "ImageStripPanel";
        }

        public Task<Mat> GetImage(CancellationToken token)
        {
            return Task.FromResult(GetImage());
        }

        public Mat GetImage()
        {
            if (listView1.SelectedIndices.Count == 0) return null;

            var path = listView1.SelectedItems[0].ImageKey;

            return new Mat(path);
        }

        public string GetImagePath()
        {
            if (listView1.SelectedIndices.Count == 0) return null;
            var path = listView1.SelectedItems[0].Tag as string;
            if (path == null) return null;
            return path;
        }

        public bool StopOnErrors
        {
            get => ckbStopOnError.Checked;
            set => ckbStopOnError.Checked = value;
        }

        public bool StopOnNoErrors
        {
            get => ckbStopOnNoError.Checked;
            set => ckbStopOnNoError.Checked = value;
        }


        public void InformImageProcessed(bool result)
        {
            if (!result)
            {
                if (ckbStopOnError.Checked)
                {
                    btnPlay.Checked = false;
                }
            }
            else
            {
                if (ckbStopOnNoError.Checked)
                {
                    btnPlay.Checked = false;
                }
            }
        }

        public void RemoveImage(Workflow.Datatypes.HawkeyeImage currentImage)
        {
            if (listView1.SelectedIndices.Count == 0) return;
            var index = listView1.SelectedIndices[0];
            listView1.Items.RemoveAt(index);
            if (listView1.Items.Count > 0)
            {
                if (index > listView1.Items.Count - 1) index--;
                listView1.SelectedIndices.Clear();
                listView1.SelectedIndices.Add(index);
                listView1.EnsureVisible(listView1.SelectedIndices[0]);
            }
            
        }

        public List<string> GetFileList()
        {
            return listView1.Items.Cast<ListViewItem>().Select(x => (string)x.Tag).ToList();
        }

        public void ReSelect()
        {
            if(listView1.SelectedIndices.Count == 0) return;
            var index = listView1.SelectedIndices[0];
            listView1.SelectedIndices.Clear();
            listView1.SelectedIndices.Add(index);
            listView1.EnsureVisible(listView1.SelectedIndices[0]);
        }

        public void SelectImage(string nextFile)
        {
            var index = listView1.Items.Cast<ListViewItem>().Where(x => (string)x.Tag == nextFile).Select(x => x.Index).FirstOrDefault();
            if (index == -1) return;
            listView1.SelectedIndices.Clear();
            listView1.SelectedIndices.Add(index);
            listView1.EnsureVisible(listView1.SelectedIndices[0]);

        }
    }
}
