using MainShell.PageCalib.OriginCalib.Model;
using Stylet;
using System;
using System.Windows.Media;

namespace MainShell.PageCalib.OriginCalib.ViewModel
{
    public class CalibrationAxisViewModel : PropertyChangedBase
    {
        private static readonly double OffsetTolerance = 0.05;
        private static readonly Brush InactiveBrush = CreateFrozenBrush(0xCC, 0xCC, 0xCC);
        private static readonly Brush InToleranceBrush = CreateFrozenBrush(0x28, 0xA7, 0x45);
        private static readonly Brush WarningBrush = CreateFrozenBrush(0xFD, 0x7E, 0x14);

        private readonly CalibrationAxisItem _item;

        public CalibrationAxisItem Item => _item;

        public string AxisName
        {
            get { return _item.AxisName; }
            set { _item.AxisName = value; NotifyOfPropertyChange(nameof(AxisName)); }
        }

        public double TargetPosition
        {
            get { return _item.TargetPosition; }
            set
            {
                _item.TargetPosition = value;
                NotifyOfPropertyChange(nameof(TargetPosition));
                UpdateOffset();
            }
        }

        public double LastPosition
        {
            get { return _item.LastPosition; }
            set
            {
                _item.LastPosition = value;
                NotifyOfPropertyChange(nameof(LastPosition));
                UpdateOffset();
            }
        }

        public double Offset
        {
            get { return _item.Offset; }
            private set
            {
                _item.Offset = value;
                NotifyOfPropertyChange(nameof(Offset));
                NotifyOfPropertyChange(nameof(OffsetText));
                NotifyOfPropertyChange(nameof(OffsetBrush));
                NotifyOfPropertyChange(nameof(StatusBrush));
            }
        }

        public bool IsCalibrated
        {
            get { return _item.IsCalibrated; }
            set
            {
                _item.IsCalibrated = value;
                NotifyOfPropertyChange(nameof(IsCalibrated));
                NotifyOfPropertyChange(nameof(OffsetText));
                NotifyOfPropertyChange(nameof(OffsetBrush));
                NotifyOfPropertyChange(nameof(StatusBrush));
            }
        }

        public string OffsetText
        {
            get
            {
                if (!IsCalibrated) return "-";
                return Offset >= 0 ? string.Format("+{0:F3}", Offset) : string.Format("{0:F3}", Offset);
            }
        }

        public Brush OffsetBrush
        {
            get
            {
                if (!IsCalibrated) return Brushes.Gray;
                return Math.Abs(Offset) <= OffsetTolerance ? InToleranceBrush : WarningBrush;
            }
        }

        public Brush StatusBrush
        {
            get
            {
                if (!IsCalibrated) return InactiveBrush;
                return Math.Abs(Offset) <= OffsetTolerance ? InToleranceBrush : WarningBrush;
            }
        }

        public CalibrationAxisViewModel(CalibrationAxisItem item)
        {
            _item = item ?? throw new ArgumentNullException(nameof(item));
        }

        public void Reset()
        {
            LastPosition = 0;
            IsCalibrated = false;
        }

        private void UpdateOffset()
        {
            Offset = Math.Round(_item.LastPosition, 3);
        }

        private static Brush CreateFrozenBrush(byte red, byte green, byte blue)
        {
            var brush = new SolidColorBrush(Color.FromRgb(red, green, blue));
            brush.Freeze();
            return brush;
        }
    }
}
