using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Threading;
using Inspectron.Camera.Image;

namespace Inspectron.Camera.Emulation
{
    public class EmulationCamera : ICamera
    {
        private string[] _selectedFiles = new string[0];
        private int _index = 0;
        private string _currentFolder;

        public void Reset()
        {
            _index = 0;
        }

        public EmulationCamera(ICameraProvider provider)
        {
            Provider = provider;
        }

        public bool SingleRun { get; set; }=false;


        public void SetFolder(string imagesFolder)
        {
            try
            {
                _currentFolder = imagesFolder;
                var path = Path.Combine("..","Data","Emulation", imagesFolder);
                _selectedFiles = Directory.GetFiles(path, "*.bmp")
                    .Concat(Directory.GetFiles(path, "*.png"))
                    .Concat(Directory.GetFiles(path, "*.jpg"))
                    .Where(x => !Path.GetFileNameWithoutExtension(x).Contains("_analysis"))
                    .ToArray();
            }
            catch
            {
            }
        }

        public void SetFolderAbsolute(string imagesFolder)
        {
            try
            {
                _currentFolder = imagesFolder;
                var path = imagesFolder;
                _selectedFiles = Directory.GetFiles(path, "*.bmp")
                    .Concat(Directory.GetFiles(path, "*.png"))
                    .Concat(Directory.GetFiles(path, "*.jpg"))
                    .Where(x => !Path.GetFileNameWithoutExtension(x).Contains("_analysis"))
                    .ToArray();
            }
            catch
            {
            }
        }

        public string Name { get; set; } = "Emulation";

        public void Open()
        {
            IsOpen = true;
        }

        public bool IsOpen { get; private set; }

        public void Close()
        {
            IsOpen = false;
        }

        public bool IsGrabbingContinuous { get; }

        public void StartGrabContinuous()
        {
            throw new NotImplementedException();
        }

        public void StopGrabContinuous()
        {
            throw new NotImplementedException();
        }

        public void LoadParameters(string parametersFile)
        {
        }

        public void SaveParameters(string parametersFile)
        {
            throw new NotImplementedException();
        }

        public void SaveParametersToDevice()
        {
            throw new NotImplementedException();
        }

        public int CycleDelay { get; set; } = 1;
        public int PerImageDelay { get; set; } = 5000;
        public event Action OnLoopOver=delegate{};
        public IImage GrabSingle()
        {
            if (_selectedFiles.Length == 0) return null;
            var id = (_index) % _selectedFiles.Length;
            if (id == 0)
            {
                if(_index>0)
                    OnLoopOver();
                if (SingleRun&&_index>0)
                {
                    // infinite sleep
                    Thread.Sleep(Timeout.Infinite);
                }
                Console.WriteLine("starting new emulation cycle");
                Thread.Sleep(CycleDelay);
            }
            else
            {
                Thread.Sleep(PerImageDelay);
            }

            var path = _selectedFiles[id];
            _index++;
            var bmp = new Bitmap(path);

            Console.WriteLine($"Getting image {path}");

            return new BitmapImage(bmp);
        }

        public event ImageGrabbedHandler ImageGrabbed;
        public ICameraCapabilities Capabilities { get; } = new EmulationCameraCapabilities();

        public IEnumerable<ICameraParameter> Parameters => new List<ICameraParameter>()
        {
            new CameraParameter("Folder", () => this.CurrentFolder, x => CurrentFolder = (string) x)
        };

        public ICameraProvider Provider { get; }

        public string CurrentFolder
        {
            get => _currentFolder;
            set => _currentFolder = value;
        }

        public int Index
        {
            get => _index;
            set => _index = value;
        }

        public IEnumerable<(Bitmap bmp, string path)> GetImages()
        {
            foreach (string selectedFile in _selectedFiles)
            {
                yield return (new Bitmap(selectedFile), selectedFile);
            }
        }
    }
}