using System.Diagnostics;
using System.Reflection;
using Hawkeye.VisionBuilder.Workflow.ColorStudioClasses;
using Hawkeye.VisionBuilder.Workflow.Datatypes;
using Hawkeye.VisionBuilder.Workflow.Operations.Attributes;
using OpenCvSharp;

namespace Hawkeye.VisionBuilder.Workflow.Operations.Filters;

[Category("Filters")]
public class ColorProfileOperation:BaseOperation
{
    private FilePath _colorProfilePath = new FilePath(){Format = "*.colorprofile|*.colorprofile" };


    bool _initialized = false;
    private CategoryTree _categoryTree;
    private CategoryItem _categoryItem;
    private SelectFromList _category;


    public Action RunColorStudio => RunColorStudioInternal;

    void RunColorStudioInternal()
    {
        var colorStudioPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), @"..\ColorStudio\Hawkeye.ColorStudio.exe");
        var process = Process.Start(colorStudioPath, new[]{ _colorProfilePath.Path,_lastImagePath,Category.Value});
        process?.WaitForExit();
        _initialized=false;
    }


    public ColorProfileOperation()
    {
        _category = new SelectFromList()
        {
            Value = "none",
            GetList = ()=> GetCategories()
        };
    }

    private List<string> GetCategories()
    {
        var list = new List<string>();
        if (_categoryTree != null)
        {
            list = _categoryTree.CategoryItems.Select(c => c.Name).ToList();
        }
        return list;
    }

    public SelectFromList Category
    {
        get => _category;
        set
        {
            _category = value;
            _initialized = false;
        }
    }

    public FilePath ColorProfilePath
    {
        get => _colorProfilePath;
        set
        {
            _initialized=false;
            _colorProfilePath = value;
        }
    }

    string _lastImagePath = "";

    protected override void InterpretInternal(Context context)
    {
        if (!CheckImageExists(context)) return;
        if (!CheckColorful(context)) return;
        _lastImagePath = context.ActiveImage?.Filename;
        if (!_initialized)
        {
            if (!File.Exists(ColorProfilePath?.Path))
            {
                this.SetError("Color profile file not found");
                
                Result=false;
                return;
            }
            _categoryTree = CategoryTree.LoadFromFile(ColorProfilePath.Path);
            _categoryItem = _categoryTree.CategoryItems.FirstOrDefault(c => c.Name == Category.Value);
            if (_categoryItem == null)
            {
                this.SetError("Category not found");
                Result=false;
                return;
            }

            _initialized = true;
        }
        var hsv = context.ActiveImage.ImageData.CvtColor(ColorConversionCodes.BGR2HSV_FULL);
        var filters = _categoryItem.Filters;
        
        
        int index = 0;
        var resized = hsv.Resize(new Size(256,256),interpolation:InterpolationFlags.Nearest);
        Mat res = new Mat(resized.Size(), MatType.CV_8UC1, (Scalar)0);
        foreach (var filter in filters)
        {
            
            filter.Transform(ref resized, ref res);
            
            index++;
        }
        var upsampled = res.Resize(hsv.Size(), interpolation:InterpolationFlags.Nearest);

        context.ActiveImage = new HawkeyeImage() {ImageData = upsampled };

        
    }

    public override void Save(BinaryWriter bw)
    {
        base.Save(bw);
        bw.Write(_colorProfilePath.Path);
        bw.Write(_category.Value);
    }

    public override void Load(BinaryReader br)
    {
        base.Load(br);
        _colorProfilePath.Path = EnsureRelativePath(br.ReadString());
        _category.Value = br.ReadString();
        _initialized = false;
    }

    public override void Save(Dictionary<string, object> dict)
    {
        base.Save(dict);
        dict[nameof(ColorProfilePath)] = ColorProfilePath.Path;
        dict[nameof(Category)] = Category.Value;
    }

    public override void Load(Dictionary<string, object> dict)
    {
        base.Load(dict);
        if (dict.ContainsKey(nameof(ColorProfilePath)))
            ColorProfilePath.Path = EnsureRelativePath(dict[nameof(ColorProfilePath)].ToString());
        if (dict.ContainsKey(nameof(Category)))
            Category.Value = dict[nameof(Category)].ToString();
        _initialized = false;
    }

    string EnsureRelativePath(string path)
    {
        if (path.StartsWith(".."))
        {
            return path;
        }
        path = Path.GetFullPath(path);
        var dir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
        path = Path.GetRelativePath(dir, path);
        return path;
    }
}