using MainShell.Common;
using MainShell.Common.Display.ViewModel;
using MainShell.Common.ViewModel;
using MainShell.Common.VisionTemple.ViewModel;
using MainShell.Hardware;
using MainShell.Log;
using MainShell.Models;
using MainShell.Motion;
using MainShell.Recipe.Models;
using MwFramework.Device;
using MwFramework.ManagerService;
using Stylet;
using System;
using System.Windows;

namespace MainShell.Recipe.ViewModel
{
    public class WaferTeachViewModel : CameraBaseViewModel
    {
        private WaferRecipe _waferRecipe;
        private readonly HardwareManager _hardwareManager;
        private readonly IWindowManager _windowManager;
        private readonly SafeAxisMotion _safeAxisMotion;
        private readonly VisionTempleWindowViewModel _visionTempleWindowViewModel;

        public WaferRecipe WaferRecipe
        {
            get { return _waferRecipe; }
            set { SetAndNotify(ref _waferRecipe, value); }
        }

        public WaferTeachViewModel(
            HardwareManager hardwareManager,
            IWindowManager windowManager,
            SafeAxisMotion safeAxisMotion,
            VisionTempleWindowViewModel visionTempleWindowViewModel,
            CameraAxisViewModel cameraAxisViewModel)
        {
            _hardwareManager = hardwareManager ?? throw new ArgumentNullException(nameof(hardwareManager));
            _windowManager = windowManager ?? throw new ArgumentNullException(nameof(windowManager));
            _safeAxisMotion = safeAxisMotion ?? throw new ArgumentNullException(nameof(safeAxisMotion));
            _visionTempleWindowViewModel = visionTempleWindowViewModel ?? throw new ArgumentNullException(nameof(visionTempleWindowViewModel));
            CameraAxisViewModel = cameraAxisViewModel ?? throw new ArgumentNullException(nameof(cameraAxisViewModel));
            CameraAxisViewModel.CameraAxisDevices.HardwareDeviceList = _hardwareManager.CameraAxisManager.TopCameraWsAxisDevices;
        }

        public void TeachStartPoint()
        {
            try
            {
                IAxis axisX;
                IAxis axisY;
                if (!TryGetScanAxes(out axisX, out axisY))
                {
                    return;
                }

                WaferRecipe.ScanSettings.StartPointX = GetAxisPosition(axisX);
                WaferRecipe.ScanSettings.StartPointY = GetAxisPosition(axisY);
            }
            catch (Exception ex)
            {
                LogManager.LogSysError(ex);
                ShowOperationFailed(ex.Message);
            }
        }

        public void MoveToStartPoint()
        {
            try
            {
                IAxis axisX;
                IAxis axisY;
                if (!TryGetScanAxes(out axisX, out axisY))
                {
                    return;
                }

                _safeAxisMotion.SafeMove(
                    MotionMoveRequest.ForAxis(axisX, WaferRecipe.ScanSettings.StartPointX),
                    MotionMoveRequest.ForAxis(axisY, WaferRecipe.ScanSettings.StartPointY));
            }
            catch (Exception ex)
            {
                LogManager.LogSysError(ex);
                ShowOperationFailed(ex.Message);
            }
        }

        public void OpenVisionParameterSetting()
        {
            CameraConfig cameraConfig = new CameraConfig();
            UpCamLightConfig lightConfig = new UpCamLightConfig();
            CameraSettingsViewModel settingsViewModel = new CameraSettingsViewModel(_windowManager, _hardwareManager);
            settingsViewModel.Initialize(cameraConfig, lightConfig, CameraType.TopWsCamera);
            _windowManager.ShowDialog(settingsViewModel);
        }

        public void MakeTemplate()
        {
            try
            {
                _visionTempleWindowViewModel.ShowWindow();
            }
            catch (Exception ex)
            {
                LogManager.LogSysError(ex);
                LocalizedMessageBox.ShowFormat(
                    MessageKey.OriginCalibOpenVisionTemplateFailed,
                    MessageKey.TitleError,
                    MessageBoxButton.OK,
                    MessageBoxImage.Error,
                    ex.Message);
            }
        }

        private bool TryGetScanAxes(out IAxis axisX, out IAxis axisY)
        {
            axisX = null;
            axisY = null;

            if (WaferRecipe == null || WaferRecipe.ScanSettings == null)
            {
                return false;
            }

            if (CameraAxisViewModel == null || CameraAxisViewModel.CameraAxisDevices == null || CameraAxisViewModel.CameraAxisDevices.SelectedHardwareDevice == null)
            {
                LocalizedMessageBox.Show(MessageKey.DeviceNotInitialized, MessageKey.TitleWarning, MessageBoxButton.OK, MessageBoxImage.Warning);
                return false;
            }

            HardwareDevice selectedHardwareDevice = CameraAxisViewModel.CameraAxisDevices.SelectedHardwareDevice;
            axisX = selectedHardwareDevice.AxisX;
            axisY = selectedHardwareDevice.AxisY;
            if (axisX == null || axisY == null)
            {
                LocalizedMessageBox.Show(MessageKey.DeviceNotInitialized, MessageKey.TitleWarning, MessageBoxButton.OK, MessageBoxImage.Warning);
                return false;
            }

            return true;
        }

        private static double GetAxisPosition(IAxis axis)
        {
            if (axis == null)
            {
                throw new ArgumentNullException(nameof(axis));
            }

            return axis.State != null ? axis.State.ActualPos : axis.GetPositionImmediate();
        }

        private static void ShowOperationFailed(string message)
        {
            string title = LanguageResourceHelper.GetString(MessageKey.TitleError);
            if (string.IsNullOrWhiteSpace(message))
            {
                MwMessageBox.Show(LanguageResourceHelper.GetString(MessageKey.CommonOperationFailed), title, MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }

            MwMessageBox.Show(message, title, MessageBoxButton.OK, MessageBoxImage.Error);
        }
    }
}
