using MainShell.Common;
using MainShell.Log;
using MainShell.Vision;
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;

namespace MainShell.Motion
{
    /// <summary>
    /// 中心识别实现
    /// 通过模板匹配服务识别目标中心
    /// </summary>
    public class CenterRecognizer : ICenterRecognizer
    {
        private readonly IFindTemplateService _findTemplateService;
        private readonly IFindEdgeCircleService _findEdgeCircleService;

        public CenterRecognizer(
            IFindTemplateService findTemplateService,
            IFindEdgeCircleService findEdgeCircleService)
        {
            _findTemplateService = findTemplateService ?? throw new ArgumentNullException(nameof(findTemplateService));
            _findEdgeCircleService = findEdgeCircleService ?? throw new ArgumentNullException(nameof(findEdgeCircleService));
        }

        /// <summary>
        /// 识别图像中心坐标
        /// </summary>
        public Task<(double CenterX, double CenterY)?> RecognizeCenterAsync(
            CameraType camera,
            int timeoutMilliseconds,
            CancellationToken cancellationToken)
        {
            return RecognizeCenterAsync(
                camera,
                timeoutMilliseconds,
                new CenterRecognitionParameters(),
                cancellationToken);
        }

        /// <summary>
        /// 识别图像中心坐标
        /// </summary>
        public async Task<(double CenterX, double CenterY)?> RecognizeCenterAsync(
            CameraType camera,
            int timeoutMilliseconds,
            CenterRecognitionParameters parameters,
            CancellationToken cancellationToken)
        {
            if (parameters == null)
            {
                throw new ArgumentNullException(nameof(parameters));
            }

            try
            {
                using (CancellationTokenSource cts = new CancellationTokenSource(timeoutMilliseconds))
                using (CancellationTokenSource linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, cts.Token))
                {
                    string.Format(
                        "CenterRecognizer: Starting template recognition from camera '{0}' (timeout={1}ms, template='{2}', minScore={3}).",
                        camera,
                        timeoutMilliseconds,
                        parameters.TemplatePath,
                        parameters.MinScore).LogInfo();
                    VisionProcessResult result = null;
                    double centerX = 0;
                    double centerY = 0;
                    switch (parameters.Type)
                    {
                        case CenterRecognitionType.Template:
                            {
                                FindTemplateRequest request = BuildFindTemplateRequest(camera, timeoutMilliseconds,parameters);
                                var templateResult = await _findTemplateService.ProcessAsync(request,linkedCts.Token).ConfigureAwait(false);
                                if (templateResult.Succeeded && templateResult.Data != null)
                                {
                                    centerX = templateResult.Data.CenterX;
                                    centerY = templateResult.Data.CenterY;
                                }
                                else
                                {
                                    string.Format(
                                        "CenterRecognizer: Template recognition failed for camera '{0}': {1}",
                                        camera,
                                        templateResult.Message).LogSysError();
                                    return null;
                                }
                                break;
                            }
                        case CenterRecognitionType.EdgeCircle:
                            {
                                FindEdgeCircleRequest request = BuildFindEdgeCircleRequest(camera,timeoutMilliseconds, parameters);
                                var circleResult = await _findEdgeCircleService.ProcessAsync(request,linkedCts.Token).ConfigureAwait(false);
                                if (circleResult.Succeeded && circleResult.Data != null)
                                {
                                    centerX = circleResult.Data.CenterX;
                                    centerY = circleResult.Data.CenterY;
                                }
                                else
                                {
                                    string.Format(
                                        "CenterRecognizer: Edge circle recognition failed for camera '{0}': {1}",
                                        camera,
                                        circleResult.Message).LogSysError();
                                    return null;
                                }
                                break;
                            }
                    }

                    string.Format(
                        "CenterRecognizer: Recognition completed: X={0:F4}, Y={1:F4}",
                        centerX,
                        centerY).LogInfo();

                    return (centerX, centerY);
                }
            }
            catch (OperationCanceledException)
            {
                string.Format(
                    "CenterRecognizer: Template recognition timed out for camera '{0}'.",
                    camera).LogSysError();
                return null;
            }
            catch (Exception ex)
            {
                string.Format(
                    "CenterRecognizer: Template recognition failed for camera '{0}': {1}",
                    camera,
                    ex.Message).LogSysError();
                return null;
            }
        }

        private static FindTemplateRequest BuildFindTemplateRequest(
            CameraType camera,
            int timeoutMilliseconds,
            CenterRecognitionParameters parameters)
        {
            FindTemplateParameters findTemplateParameters = new FindTemplateParameters();
            findTemplateParameters.MinScore = parameters.MinScore;
            findTemplateParameters.TemplatePath = parameters.TemplatePath;
            findTemplateParameters.UseRoi = parameters.UseRoi;
            findTemplateParameters.RoiName = parameters.RoiName;

            FindTemplateRequest request = new FindTemplateRequest();
            request.CameraSource = camera;
            request.CaptureOptions = CameraCaptureOptions.CreateStream(timeoutMilliseconds);
            request.Parameters = findTemplateParameters;
            request.TimeoutMilliseconds = timeoutMilliseconds;
            return request;
        }

        private static FindEdgeCircleRequest BuildFindEdgeCircleRequest(
              CameraType camera,
              int timeoutMilliseconds,
              CenterRecognitionParameters parameters)
        {
            FindEdgeCircleParameters findEdgeCircleParameters = new FindEdgeCircleParameters();
            findEdgeCircleParameters.RoiRect = parameters.rectangle;

            FindEdgeCircleRequest request = new FindEdgeCircleRequest();
            request.CameraSource = camera;
            request.CaptureOptions = CameraCaptureOptions.CreateStream(timeoutMilliseconds);
            request.Parameters = findEdgeCircleParameters;
            request.TimeoutMilliseconds = timeoutMilliseconds;
            return request;
        }
    }
}
