using MainShell.EventArgsFolder;
using MainShell.Log;
using MainShell.Vision;
using MwFramework.Device;
using MwFramework.Device.Model;
using Stylet;
using System;
using System.Collections.Generic;
using System.Linq;

using AppCameraType = MainShell.Common.CameraType;

namespace MainShell.ToolBox.ViewModel
{
    public class VisionDisplayTestState : PropertyChangedBase
    {
        private AppCameraType _selectedCameraType = AppCameraType.TopPositionCamera;

        public AppCameraType SelectedCameraType
        {
            get
            {
                return _selectedCameraType;
            }
            set
            {
                SetAndNotify(ref _selectedCameraType, value);
            }
        }

        private bool _clearShapesBeforeDisplay = true;

        public bool ClearShapesBeforeDisplay
        {
            get
            {
                return _clearShapesBeforeDisplay;
            }
            set
            {
                SetAndNotify(ref _clearShapesBeforeDisplay, value);
            }
        }

        private string _statusMessage = "请选择主界面相机区域后发送测试事件。";

        public string StatusMessage
        {
            get
            {
                return _statusMessage;
            }
            set
            {
                SetAndNotify(ref _statusMessage, value);
            }
        }
    }

    public class VisionDisplayTestViewModel : PropertyChangedBase
    {
        private const int ImageWidth = 320;
        private const int ImageHeight = 240;
        private readonly IEventAggregator _eventAggregator;
        private readonly VisionDisplayTestState _state;
        private readonly AppCameraType[] _cameraTypes;

        public VisionDisplayTestState State
        {
            get
            {
                return _state;
            }
        }

        public IEnumerable<AppCameraType> CameraTypes
        {
            get
            {
                return _cameraTypes;
            }
        }

        public VisionDisplayTestViewModel(IEventAggregator eventAggregator)
        {
            _eventAggregator = eventAggregator ?? throw new ArgumentNullException(nameof(eventAggregator));
            _state = new VisionDisplayTestState();
            _cameraTypes = Enum.GetValues(typeof(AppCameraType)).Cast<AppCameraType>().ToArray();
        }

        public void SendImageEvent()
        {
            try
            {
                CameraData cameraData = CreateTestCameraData();
                DisplayImageEventArgs message = new DisplayImageEventArgs(State.SelectedCameraType, cameraData);
                _eventAggregator.Publish(message);
                State.StatusMessage = $"已发送图片事件到 {State.SelectedCameraType}，请查看主界面相机区域。";
            }
            catch (Exception ex)
            {
                State.StatusMessage = $"发送图片事件失败：{ex.Message}";
                ($"VisionDisplayTestViewModel.SendImageEvent exception: {ex}").LogSysError();
            }
        }

        public void SendDisplayEvent()
        {
            try
            {
                FindTemplateResult result = CreateTestTemplateResult();
                DisplayFindTemplateResultEventArgs message = new DisplayFindTemplateResultEventArgs(
                    State.SelectedCameraType,
                    result,
                    State.ClearShapesBeforeDisplay);
                _eventAggregator.Publish(message);
                State.StatusMessage = $"已发送结果显示事件到 {State.SelectedCameraType}，请查看主界面图形叠加。";
            }
            catch (Exception ex)
            {
                State.StatusMessage = $"发送结果显示事件失败：{ex.Message}";
                ($"VisionDisplayTestViewModel.SendDisplayEvent exception: {ex}").LogSysError();
            }
        }

        public void ClearDisplayEvent()
        {
            try
            {
                DisplayFindTemplateResultEventArgs message = new DisplayFindTemplateResultEventArgs(
                    State.SelectedCameraType,
                    null,
                    true);
                _eventAggregator.Publish(message);
                State.StatusMessage = $"已清空 {State.SelectedCameraType} 的图形叠加。";
            }
            catch (Exception ex)
            {
                State.StatusMessage = $"清空结果显示失败：{ex.Message}";
                ($"VisionDisplayTestViewModel.ClearDisplayEvent exception: {ex}").LogSysError();
            }
        }

        private static CameraData CreateTestCameraData()
        {
            byte[] buffer = new byte[ImageWidth * ImageHeight * 3];

            for (int y = 0; y < ImageHeight; y++)
            {
                for (int x = 0; x < ImageWidth; x++)
                {
                    int offset = ((y * ImageWidth) + x) * 3;
                    buffer[offset] = (byte)((x * 255) / ImageWidth);
                    buffer[offset + 1] = (byte)((y * 255) / ImageHeight);
                    buffer[offset + 2] = 40;
                }
            }

            AddCrossMark(buffer, ImageWidth / 2, ImageHeight / 2, 36, 255, 255, 255);

            CameraData cameraData = new CameraData(
                buffer,
                (uint)ImageWidth,
                (uint)ImageHeight,
                CustomPixelFormat.Rgb8Packed,
                0L,
                DateTime.Now,
                false);
            cameraData.Bit = 3;
            return cameraData;
        }

        private static void AddCrossMark(byte[] buffer, int centerX, int centerY, int halfLength, byte blue, byte green, byte red)
        {
            for (int offsetX = -halfLength; offsetX <= halfLength; offsetX++)
            {
                SetPixel(buffer, centerX + offsetX, centerY, blue, green, red);
            }

            for (int offsetY = -halfLength; offsetY <= halfLength; offsetY++)
            {
                SetPixel(buffer, centerX, centerY + offsetY, blue, green, red);
            }
        }

        private static void SetPixel(byte[] buffer, int x, int y, byte blue, byte green, byte red)
        {
            if (x < 0 || x >= ImageWidth || y < 0 || y >= ImageHeight)
            {
                return;
            }

            int offset = ((y * ImageWidth) + x) * 3;
            buffer[offset] = blue;
            buffer[offset + 1] = green;
            buffer[offset + 2] = red;
        }

        private static FindTemplateResult CreateTestTemplateResult()
        {
            FindTemplateResult result = new FindTemplateResult();
            result.CenterX = 160d;
            result.CenterY = 120d;
            result.Score = 0.987d;
            result.Contour = new FindTemplateContourResult
            {
                StartX = 90d,
                StartY = 70d,
                EndX = 230d,
                EndY = 170d
            };

            result.Circles.Add(new FindTemplateCircleResult
            {
                CenterX = 160d,
                CenterY = 120d,
                Radius = 24d
            });
            result.Lines.Add(new FindTemplateLineResult
            {
                StartX = 80d,
                StartY = 40d,
                EndX = 260d,
                EndY = 200d
            });
            result.Rectangles.Add(new FindTemplateRectangleResult
            {
                StartX = 110d,
                StartY = 85d,
                Width = 90d,
                Height = 48d,
                Angle = Math.PI / 9d
            });
            return result;
        }
    }
}
