using MwFramework.ManagerService;
using Stylet;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MainShell.Recipe.Models
{
    public class PidAxisOption
    {
        public string AxisName { get; set; }

        public int AxisIndex { get; set; }
    }

    public static class PidAxisCatalog
    {
        private static readonly Dictionary<int, string> _axisNameByIndex = new Dictionary<int, string>();
        private static readonly Dictionary<string, int> _axisIndexByName = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);

        public static void SetAxisOptions(IEnumerable<PidAxisOption> axisOptions)
        {
            _axisNameByIndex.Clear();
            _axisIndexByName.Clear();

            if (axisOptions == null)
            {
                return;
            }

            foreach (PidAxisOption axisOption in axisOptions)
            {
                if (axisOption == null || string.IsNullOrWhiteSpace(axisOption.AxisName))
                {
                    continue;
                }

                _axisNameByIndex[axisOption.AxisIndex] = axisOption.AxisName;
                _axisIndexByName[axisOption.AxisName] = axisOption.AxisIndex;
            }
        }

        public static string GetAxisName(int axisIndex)
        {
            string axisName;
            return _axisNameByIndex.TryGetValue(axisIndex, out axisName) ? axisName : string.Empty;
        }

        public static bool TryGetAxisIndex(string axisName, out int axisIndex)
        {
            if (string.IsNullOrWhiteSpace(axisName))
            {
                axisIndex = -1;
                return false;
            }

            return _axisIndexByName.TryGetValue(axisName, out axisIndex);
        }
    }

    public class AxisPIDParameter : PropertyChangedBase, IParameterItem
    {
        private bool _isSynchronizingAxis;
        private string _moduleName;

        public string ModuleName
        {
            get { return _moduleName; }
            set
            {
                if (SetAndNotify(ref _moduleName, value))
                {
                    SyncAxisIndexFromModuleName();
                }
            }
        }

        private int _axisIndex;

        public int AxisIndex
        {
            get { return _axisIndex; }
            set
            {
                if (SetAndNotify(ref _axisIndex, value))
                {
                    SyncModuleNameFromAxisIndex();
                }
            }
        }
        private PIDLabel<double> _pA_SLVKP = new PIDLabel<double>() { Name = "PA_SLVKP_", Value = 0 };
        /// <summary>
        /// 速度环KP
        /// </summary>
        public PIDLabel<double> PA_SLVKP
        {
            get { return _pA_SLVKP; }
            set { SetAndNotify(ref _pA_SLVKP, value); }
        }

        private PIDLabel<double> _pA_SLVKI = new PIDLabel<double>() { Name = "PA_SLVKI_", Value = 0 };
        /// <summary>
        /// 速度环KI
        /// </summary>
        public PIDLabel<double> PA_SLVKI
        {
            get { return _pA_SLVKI; }
            set { SetAndNotify(ref _pA_SLVKI, value); }
        }

        private PIDLabel<double> _pA_SLVKPSF = new PIDLabel<double>() { Name = "PA_SLVKPSF_", Value = 0 };
        /// <summary>
        /// 速度环KP Settle因子
        /// </summary>
        public PIDLabel<double> PA_SLVKPSF
        {
            get { return _pA_SLVKPSF; }
            set { SetAndNotify(ref _pA_SLVKPSF, value); }
        }

        private PIDLabel<double> _pA_SLVKPIF = new PIDLabel<double>() { Name = "PA_SLVKPIF_", Value = 0 };
        /// <summary>
        /// 速度环KP Iddle因子
        /// </summary>
        public PIDLabel<double> PA_SLVKPIF
        {
            get { return _pA_SLVKPIF; }
            set { SetAndNotify(ref _pA_SLVKPIF, value); }
        }

        private PIDLabel<double> _pA_SLVKISF = new PIDLabel<double>() { Name = "PA_SLVKISF_", Value = 0 };
        /// <summary>
        /// 速度环KI Settle因子
        /// </summary>
        public PIDLabel<double> PA_SLVKISF
        {
            get { return _pA_SLVKISF; }
            set { SetAndNotify(ref _pA_SLVKISF, value); }
        }

        private PIDLabel<double> _pA_SLVKIIF = new PIDLabel<double>() { Name = "PA_SLVKIIF_", Value = 0 };
        /// <summary>
        /// 速度环KI Iddle因子   
        /// </summary>
        public PIDLabel<double> PA_SLVKIIF
        {
            get { return _pA_SLVKIIF; }
            set { SetAndNotify(ref _pA_SLVKIIF, value); }
        }



        private PIDLabel<double> _pA_SLPKP = new PIDLabel<double>() { Name = "PA_SLPKP_", Value = 0 };
        /// <summary>
        /// 位置环的KP
        /// </summary>
        public PIDLabel<double> PA_SLPKP
        {
            get { return _pA_SLPKP; }
            set { SetAndNotify(ref _pA_SLPKP, value); }
        }

        private PIDLabel<double> _pA_SLPKPIF = new PIDLabel<double>() { Name = "PA_SLPKPIF_", Value = 0 };
        /// <summary>
        /// 位置环的KP的Idel因子
        /// </summary>
        public PIDLabel<double> PA_SLPKPIF
        {
            get { return _pA_SLPKPIF; }
            set { SetAndNotify(ref _pA_SLPKPIF, value); }
        }

        private PIDLabel<double> _pA_SLPKPSF = new PIDLabel<double>() { Name = "PA_SLPKPSF_", Value = 0 };
        /// <summary>
        /// 位置环的KP的Settle因子
        /// </summary>
        public PIDLabel<double> PA_SLPKPSF
        {
            get { return _pA_SLPKPSF; }
            set { SetAndNotify(ref _pA_SLPKPSF, value); }
        }

        private PIDLabel<double> _pA_SLAFF = new PIDLabel<double>() { Name = "PA_SLAFF_", Value = 0 };
        /// <summary>
        /// 加速度前馈
        /// </summary>
        public PIDLabel<double> PA_SLAFF
        {
            get { return _pA_SLAFF; }
            set { SetAndNotify(ref _pA_SLAFF, value); }
        }

        private PIDLabel<double> _pA_SLJFF = new PIDLabel<double>() { Name = "PA_SLJFF_", Value = 0 };
        /// <summary>
        /// 加加速度前馈
        /// </summary>
        public PIDLabel<double> PA_SLJFF
        {
            get { return _pA_SLJFF; }
            set { SetAndNotify(ref _pA_SLJFF, value); }
        }

        public AxisPIDParameter()
        {
        }
        public AxisPIDParameter(string moduleName)
        {
            ModuleName = moduleName;
        }

        public IParameterItem Clone()
        {
            AxisPIDParameter copy = new AxisPIDParameter
            {
                ModuleName = this.ModuleName,
                AxisIndex = this.AxisIndex,
                PA_SLVKP = this.PA_SLVKP != null ? (PIDLabel<double>)this.PA_SLVKP.Clone() : new PIDLabel<double>(),
                PA_SLVKI = this.PA_SLVKI != null ? (PIDLabel<double>)this.PA_SLVKI.Clone() : new PIDLabel<double>(),
                PA_SLVKPSF = this.PA_SLVKPSF != null ? (PIDLabel<double>)this.PA_SLVKPSF.Clone() : new PIDLabel<double>(),
                PA_SLVKPIF = this.PA_SLVKPIF != null ? (PIDLabel<double>)this.PA_SLVKPIF.Clone() : new PIDLabel<double>(),
                PA_SLVKISF = this.PA_SLVKISF != null ? (PIDLabel<double>)this.PA_SLVKISF.Clone() : new PIDLabel<double>(),
                PA_SLVKIIF = this.PA_SLVKIIF != null ? (PIDLabel<double>)this.PA_SLVKIIF.Clone() : new PIDLabel<double>(),

                PA_SLPKP = this.PA_SLPKP != null ? (PIDLabel<double>)this.PA_SLPKP.Clone() : new PIDLabel<double>(),
                PA_SLPKPIF = this.PA_SLPKPIF != null ? (PIDLabel<double>)this.PA_SLPKPIF.Clone() : new PIDLabel<double>(),
                PA_SLPKPSF = this.PA_SLPKPSF != null ? (PIDLabel<double>)this.PA_SLPKPSF.Clone() : new PIDLabel<double>(),
                PA_SLAFF = this.PA_SLAFF != null ? (PIDLabel<double>)this.PA_SLAFF.Clone() : new PIDLabel<double>(),
                PA_SLJFF = this.PA_SLJFF != null ? (PIDLabel<double>)this.PA_SLJFF.Clone() : new PIDLabel<double>()
            };

            return copy;
        }

        private void SyncAxisIndexFromModuleName()
        {
            if (_isSynchronizingAxis)
            {
                return;
            }

            int axisIndex;
            if (!PidAxisCatalog.TryGetAxisIndex(ModuleName, out axisIndex))
            {
                return;
            }

            _isSynchronizingAxis = true;
            try
            {
                SetAndNotify(ref _axisIndex, axisIndex);
            }
            finally
            {
                _isSynchronizingAxis = false;
            }
        }

        private void SyncModuleNameFromAxisIndex()
        {
            if (_isSynchronizingAxis)
            {
                return;
            }

            string axisName = PidAxisCatalog.GetAxisName(AxisIndex);
            if (string.IsNullOrWhiteSpace(axisName))
            {
                return;
            }

            _isSynchronizingAxis = true;
            try
            {
                SetAndNotify(ref _moduleName, axisName);
            }
            finally
            {
                _isSynchronizingAxis = false;
            }
        }
    }
}
