using System;
using OpenCvSharp;

namespace OpenCVStudio_v0
{
    /// <summary>
    /// Вычисляет обычный ограничивающий прямоугольник
    /// для каждого найденного контура.
    ///
    /// Изображение и сами контуры не изменяются.
    /// </summary>
    internal sealed class BoundingRectExecutor : IPipelineBlockExecutor
    {
        public string BlockType => "BoundingRect";

        public void Execute(PipelineContext context, ProjectBlock block, ProjectManager projectManager)
        {
            ArgumentNullException.ThrowIfNull(context);
            ArgumentNullException.ThrowIfNull(block);
            ArgumentNullException.ThrowIfNull(projectManager);
            ValidateContext(context, block);
            ContourData contourData = context.Contours!;
            Rect[] rectangles = new Rect[contourData.Count];
            for (int contourIndex = 0; contourIndex < contourData.Count; contourIndex++)
            {
               OpenCvSharp. Point[] contour = contourData.Contours[contourIndex];
                if (contour == null || contour.Length == 0)
                {
                    rectangles[contourIndex] = new Rect();
                    continue;
                }
                rectangles[contourIndex] = Cv2.BoundingRect(contour);
            }
            BoundingRectData boundingRectData = new BoundingRectData(rectangles);
            context.BoundingRects = boundingRectData;
            context.ResultText = CreateResultText(boundingRectData);
        }

        /// <summary>
        /// Проверяет наличие контуров.
        /// </summary>
        private static void ValidateContext(PipelineContext context, ProjectBlock block)
        {
            if (context.Contours == null)
            {
                throw new InvalidOperationException($"Перед блоком «{block.Name}» должен быть выполнен блок FindContours.");
            }
        }

        /// <summary>
        /// Создаёт текст для StatusStrip.
        /// </summary>
        private static string CreateResultText(BoundingRectData boundingRectData)
        {
            if (boundingRectData.IsEmpty)
            {
                return "BoundingRect: контуры отсутствуют.";
            }
            int largestIndex = boundingRectData.GetLargestRectangleIndex();
            Rect largestRectangle = boundingRectData.GetLargestRectangle();
            long largestRectangleArea = (long)largestRectangle.Width * largestRectangle.Height;
            return $"BoundingRect: прямоугольников {boundingRectData.Count}; наибольший №{largestIndex}; X={largestRectangle.X}, Y={largestRectangle.Y}, размер {largestRectangle.Width}×{largestRectangle.Height}; площадь рамки {largestRectangleArea} px².";
        }
    }
}