using CandyboxPlugin.Recipe;
using Hawkeye.VisionBuilder.UI.Sources.Hawkeye;
using Newtonsoft.Json;
using OpenCvSharp;
using Serilog;
using VisionBuilder.UI.Common.Processing;
using VisionBuilder.UI.Common.ViewModel.Classes;

namespace CandyboxPlugin.Module;

public class CandyboxImageProcessingControl : BaseRecognitionControl
{
    private readonly CandyboxRecognitionControlSettings _settings;
    private readonly IImageSource _imageSource;
    private HistoRecipe _histoRecipe;

    public CandyboxImageProcessingControl(CandyboxRecognitionControlSettings settings, IImageSource imageSource, ILoadingService loadingService) : base(settings, loadingService)
    {
        _settings = settings;
        _imageSource = imageSource;
    }

    private const string RECIPES_DIR = @"..\Data\Recipes";
    private const string SAMPLES_DIR = @"..\Data\Samples";

    public override List<RecipeData> GetRecipesData()
    {
        var recipes = new List<RecipeData>();
        var recipeFiles = Directory.GetFiles(RECIPES_DIR, _settings.RecipeNameFilter+".json");
        foreach (var file in recipeFiles)
        {
            var name = Path.GetFileNameWithoutExtension(file);
            
            Mat? image = null;
            var filePatterns = new[]
            {
                name + ".bmp",
                "r" + name + ".bmp",
                name.Replace("recipe", "") + ".bmp"
            };

            foreach (var pattern in filePatterns)
            {
                var filePath = Path.Combine(SAMPLES_DIR, pattern);
                if (File.Exists(filePath))
                {
                    image = Cv2.ImRead(filePath);
                    break; // Exit loop after finding the first matching file
                }
                else
                {
                    Log.Debug($"File not found: {filePath}");
                }
            }



            recipes.Add(new RecipeData
            {
                RecipeName = name,
                Image = image
            });
        }
        return recipes;
    }

    protected override void Initialize(RecipeData currentRecipe)
    {
        _histoRecipe = new HistoRecipe(currentRecipe.RecipeName);
        if (_imageSource is HawkeyeCameraImageSource hawkeye)
        {
            var settings = hawkeye.Settings;
            settings.ImageSettings = settings.ImageSettings with {Lines = _histoRecipe.GetCameraWidth()};
            hawkeye.ApplySettings(settings);
        }
    }

    protected override void WarmUp()
    {

    }

    protected override (Mat originalImage, Mat analysisImage, TimeSpan processingTime, TimeSpan acquisitionTime, string[] errorNames)?
        ProcessImage(CancellationToken token)
    {
        var swTotal = System.Diagnostics.Stopwatch.StartNew();
        var swAcquision = System.Diagnostics.Stopwatch.StartNew();
        var image = _imageSource.GetImage(token).Result;
        swAcquision.Stop();
        if (image==null)
        {
            return null;
        }
            
        var res=_histoRecipe.ProcessImage(image);
        swTotal.Stop();

        var allErrors = 
            res.ErrorPoints.Select(x => "Position "+x.ToString())
                .Concat(
                    res.ErrorReason.Where(x=>x != EErrorReason.Good).Select(x=>x.ToString())
                ).ToArray();

        if (_settings.AlwaysError)
        {
                        allErrors = allErrors.Concat(new[] { "Always Error" }).ToArray();
        }

        return (image, res.ProcessedImage, swTotal.Elapsed, swAcquision.Elapsed, allErrors);

    }
}