using System.Reflection;
using Compunet.YoloV8;
using Hawkeye.VisionBuilder.Workflow.Datatypes;
using Hawkeye.VisionBuilder.Workflow.Operations.Attributes;
using Microsoft.Scripting.Runtime;
using OpenCvSharp;

namespace Hawkeye.VisionBuilder.Workflow.Operations.Scripts;

[Category("Script")]
public class CSharpProcessOperation:BaseOperation
{
    private FilePath _scriptFilePath = new FilePath() { Format = "C# dll(*.dll)|*.dll" };
    private bool _initialized;
    private object _processor;
    private MethodInfo? _method;


    public FilePath ScriptFilePath
    {
        get => _scriptFilePath;
        set
        {
            _scriptFilePath = value;
            _initialized = false;
        }
    }

    bool EnsureInitialized()
    {
        if (!_initialized)
        {
            if (!File.Exists(ScriptFilePath?.Path))
            {
                this.SetError("Script file not found");
                return false;
            }


            var absPath = Path.GetFullPath(ScriptFilePath?.Path);
            var loadContext = new PluginLoadContext(absPath);
            var assembly = loadContext.LoadFromAssemblyPath(absPath);

            // find class that has Process method
            foreach (var type in assembly.GetTypes())
            {
                var method = type.GetMethod("ProcessImage", BindingFlags.Public | BindingFlags.Instance);
                if (method != null)
                {
                    _processor = Activator.CreateInstance(type);
                    _method = method;
                    break;
                }
                
            }
            Label = Path.GetFileNameWithoutExtension(ScriptFilePath?.Path);
            _initialized = true;
        }
        return true;
    }

    protected override void InterpretInternal(Context context)
    {
        CheckImageExists(context);
        if (!EnsureInitialized()) return;

        var image = context.ActiveImage.ImageData;
        var result = (Mat)_method.Invoke(_processor, new []{ image });

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

    }
}