using System.Diagnostics;
using System.Runtime.InteropServices;
using Hawkeye.VisionBuilder.Workflow.Datatypes;
using ILGPU;
using ILGPU.Runtime;
using OpenCvSharp;

namespace Hawkeye.VisionBuilder.Workflow.ColorStudioClasses.Filters;

[Obsolete]
public class SpatialFilterItemGPU:IFilter
{
    private Mat? _mask = null;

    private MemoryBuffer1D<byte, Stride1D.Dense> _maskGpu;



    public IFilterParent Parent { get; set; }

    public bool Subtract { get; set; }

    public string? FilePath { get; set; }

    public void ReloadMask()
    {
        if (!File.Exists(FilePath))
        {
            CreateMask();
        }
        else
        if (!string.IsNullOrEmpty(FilePath))
        {
            _mask = new Mat(FilePath).CvtColor(ColorConversionCodes.BGR2GRAY);
        }
        LoadMaskToGpu();
    }

    private unsafe void LoadMaskToGpu()
    {
        var maskBytes = new Span<byte>(Mask.DataPointer, Mask.Width * Mask.Height).ToArray();
        if (_maskGpu != null)
        {
            _maskGpu.Dispose();
        }
        _maskGpu = Kernels.Accelerator.Allocate1D<byte>(maskBytes);
        

    }

    
    private static MemoryBuffer1D<byte, Stride1D.Dense>? _imageMemory;
    private static MemoryBuffer1D<byte, Stride1D.Dense>? _resMemory;
    

    public SpatialFilterItemGPU()
    {


    }

    void CreateMask()
    {
        _mask = new Mat(13005 + 256, 256, MatType.CV_8UC1, (Scalar)0);
    }

    public SpatialFilterItemGPU(CategoryItem parent) : this()
    {
        Parent = parent;
    }

    public Mat Mask
    {
        get
        {
            if (_mask == null)
            {
                if (FilePath != null)
                {
                    ReloadMask();
                }
                else
                {
                    CreateMask();
                }
            }

            return _mask;
        }
        set
        {
            _mask = value;
        }
    }

    private static Mat? _lastLoadedImage;
    

    public unsafe void Transform(ref Mat image, ref Mat res)
    {


        
        var w = image.Width;
        var mw = Mask.Width;
        
        
        
        if (_lastLoadedImage != image)
        {
            var imageBytes = new ReadOnlySpan<byte>(image.DataPointer, image.Width * image.Height * 3);
            _imageMemory ??= Kernels.Accelerator.Allocate1D<byte>(imageBytes.Length);
            _imageMemory.View.BaseView.CopyFromCPU(imageBytes);
            _lastLoadedImage = image;
        }

        var len = (int)_imageMemory.Length;

        _resMemory ??= Kernels.Accelerator.Allocate1D<byte>(len / 3);
        


        Kernels.SpatialKernel(len/3, w, mw, _imageMemory.View, _maskGpu.View,  _resMemory.View);
        var arr = _resMemory.GetAsArray1D();
        

        var candidates=new Mat(new[]{image.Height,image.Width}, MatType.CV_8UC1);
        candidates.SetArray(arr);


        if (Subtract && !IsSelected)
        {
            res -= candidates;
        }
        else
        {
            res |= candidates;

        }

  
        candidates.Dispose();
        

        
    }

    public void Save(BinaryWriter writer)
    {
        writer.Write(FilePath ?? "");
        writer.Write(Subtract);
    }

    public void Load(BinaryReader reader)
    {
        FilePath = reader.ReadString();
        Console.WriteLine("Loaded path:" + FilePath);
        if (FilePath.StartsWith("..\\../"))
            FilePath = FilePath.Replace("..\\../", "..\\");
        Subtract = reader.ReadBoolean();
    }

    public bool IsSelected { get; set; }


    public override string ToString()
    {
        var totalColors = 0;
        if (Mask != null)
        {
            totalColors = Mask.CountNonZero();
        }
        return $"{(Subtract ? "-" : "+")}Spatial Filter({totalColors} colors)";
    }

    
}