using FLY.Thick.FilmCasting.Common;
using FLY.Thick.FilmCasting.IService;
using FLY.Thick.FilmCasting.Server.Model;
using FObjBase;
using LiveCharts;
using LiveCharts.Configurations;
using LiveCharts.Wpf;
using Misc;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
using System.Windows.Media;

namespace FLY.Thick.FilmCasting.UI.UiModule
{
    public class ScanMmGraphVm : ScanGraphVm
    {
        


        #region 界面统计值

        /// <summary>
        /// X轴显示能显示mm
        /// </summary>
        public bool IsMmValid { get; set; }
        /// <summary>
        /// 膜开始位置 单位:分区序号
        /// </summary>
        public double FilmBeginOfBoltIndex { get; set; } = NULL_VALUE;
        public double FilmBeginOfBoltNo => FilmBeginOfBoltIndex + 1;
        /// <summary>
        /// 膜结束位置 单位:分区序号
        /// </summary>
        public double FilmEndOfBoltIndex { get; set; } = NULL_VALUE;
        public double FilmEndOfBoltNo => FilmEndOfBoltIndex + 1;



        /// <summary>
        /// 选择的位置 单位:分区序号
        /// </summary>
        public int SelectedOfBoltIndex { get; set; } = NULL_VALUE;
        public int SelectedOfBoltNo => SelectedOfBoltIndex + 1;
        /// <summary>
        /// 选择的位置宽度 单位:分区序号
        /// </summary>
        public int SelectedWidthOfBoltIndex { get; set; } = 0;

        /// <summary>
        /// 选择范围宽度 mm
        /// </summary>
        public int SelectedWidthMm { get; set; } = -1;
        /// <summary>
        /// 选择范围均值 um
        /// </summary>
        public double SelectedValueAvg { get; set; } = double.NaN;

        /// <summary>
        /// 选择点 有效
        /// </summary>
        public bool IsSelectedValid => SelectedOfBoltIndex >= 0;
        
        public double MarkOfY { get; protected set; } = NULL_VALUE;
        public int MarkOfX { get; protected set; } = NULL_VALUE;

        #endregion

        protected ScanMmGraphItemParam graphParamMm;
        public ScanMmGraphVm()
        {
            XFormatter = (x) =>
            {
                if(graphParamMm==null)
                    return $"{(int)x}";

                if (graphParamMm.IsXShowBoltNo)
                    return $"{(int)x}";

                if (!IsMmValid) 
                { 
                    //还没有膜
                    return $"{(int)x}";
                }

                int posMm = (int)BoltIndex2Mm(x-1);
                return $"{posMm}mm";                
            };
        }

        public void Init(
            ScanMmGraphItemParam graphparam,
            IBulkDbService bulkDb,
            ParamDictionary paramDictionary,
            FilmCastingProfileParam profileParam,
            IInitParamService initParamService
            )
        {
            base.Init(graphparam, bulkDb, paramDictionary, profileParam, initParamService);

            this.graphParamMm = graphparam;
        }

        protected override void Init2()
        {
            Misc.BindingOperations.SetBinding(
                ScanMmGraphParams.Current, nameof(ScanMmGraphParams.XStep),
                this, nameof(XStep));
        }

        void GetBoltIndex2MmParams(out double filmMid, out double boltWidth, out double boltIndexOfMid)
        {
            var boltMapInfo = scanData.BoltMapInfo;
            var BoltCnt = boltMapInfo.BoltCnt;
            var LeftEmptyBolts = boltMapInfo.LeftEmptyBolts;
            var RightEmptyBolts = boltMapInfo.RightEmptyBolts;
            var BoltWidth = boltMapInfo.BoltWidth;
            var UniformShrinkPercent = boltMapInfo.UniformShrinkPercent;
            var FilmWidth = scanData.FilmWidth;
            var MidOffset = boltMapInfo.MidOffset;

            //膜中心位置
            filmMid = FilmWidth / 2;

            //偏移后，中心分区序号对应的 膜位置mm
            filmMid += MidOffset;

            //中心分区序号
            boltIndexOfMid = ((BoltCnt - RightEmptyBolts) + LeftEmptyBolts) / 2.0;
            boltIndexOfMid -= 0.5;

            //每个分区真实宽度 mm
            boltWidth = BoltWidth * (1 - UniformShrinkPercent);
        }

        /// <summary>
        /// mm 转 分区序号
        /// </summary>
        /// <param name="boltIndex"></param>
        /// <returns></returns>
        double Mm2BoltIndex(double posMm) 
        {

            GetBoltIndex2MmParams(out double filmMid, out double boltWidth, out double boltIndexOfMid);

            //要查询的分区序号 与 中心分区序号的偏差
            double indexOffset = (posMm - filmMid)/ boltWidth;

            //要查询的位置mm 对应 分区序号
            double boltIndex = indexOffset + boltIndexOfMid;

            return boltIndex;
        }

        /// <summary>
        /// 分区序号 转 mm
        /// </summary>
        /// <param name="boltIndex"></param>
        /// <returns></returns>
        double BoltIndex2Mm(double boltIndex)
        {
            GetBoltIndex2MmParams(out double filmMid, out double boltWidth, out double boltIndexOfMid);

            //要查询的分区序号 与 中心分区序号的偏差
            double indexOffset = boltIndex - boltIndexOfMid;

            //要查询的分区序号 对应的 位置mm
            double posMm = filmMid + indexOffset * boltWidth;

            return posMm;
        }


        /// <summary>
        /// 更新全部状态
        /// </summary>
        protected override void UpdateAverage()
        {
            base.UpdateAverage();

            if (this.scanData == null || scanData.Thicks == null)
            {
                IsMmValid = false;
                FilmBeginOfBoltIndex = NULL_VALUE;
                FilmEndOfBoltIndex = NULL_VALUE;

                ClearSelected();

                NotifyPropertyChanged(nameof(XFormatter));
                return;
            }
 

            IsMmValid = true;
            FilmBeginOfBoltIndex = Mm2BoltIndex(0);
            FilmEndOfBoltIndex = Mm2BoltIndex(FilmWidth);
            if (IsSelectedValid) {
                CalSelectedWidth();
            }
            NotifyPropertyChanged(nameof(XFormatter));
        }
        void ClearSelected() 
        {
            SelectedOfBoltIndex = NULL_VALUE;
            SelectedWidthOfBoltIndex = 0;

            CalSelectedWidth();
            
            
        }

        protected void CalSelectedWidth() 
        {
            if (!IsSelectedValid)
            {
                SelectedWidthMm = -1;
                SelectedValueAvg = double.NaN;
            }
            else {
                double selectedMm = BoltIndex2Mm(SelectedOfBoltIndex);
                double endMm = BoltIndex2Mm(SelectedOfBoltIndex + SelectedWidthOfBoltIndex);
                SelectedWidthMm = (int)Math.Abs(endMm - selectedMm);

                if (scanData == null)
                {
                    SelectedValueAvg = double.NaN;
                }
                else
                {
                    int idx = SelectedOfBoltIndex;
                    int cnt = SelectedWidthOfBoltIndex + 1;
                    var values = scanData.Thicks;

                    if (idx < 0) idx = 0;
                    else if (idx >= values.Count())
                        idx = values.Count() - 1;
                    if (idx + cnt > values.Count())
                    {
                        cnt = values.Count() - idx;
                    }
                    SelectedValueAvg = values.Skip(idx).Take(cnt).AverageNoNull();
                }
            }

            updateMark();
        }
        
        /// <summary>
        /// 设置选择范围。 在ScanMmGraph 中调用
        /// </summary>
        /// <param name="boltNoBegin"></param>
        /// <param name="boltNoEnd"></param>
        public void SetSelected(double boltNoBegin, double boltNoEnd) 
        {
            //当没有数据时，不能选择
            if (!IsMmValid)
                return;

            int boltIndexBegin = (int)(boltNoBegin) - 1;
            int boltIndexEnd = (int)(boltNoEnd)- 1;
            if ((boltIndexBegin < FilmBeginOfBoltIndex && boltIndexEnd < FilmBeginOfBoltIndex) 
                || (boltIndexBegin > FilmEndOfBoltIndex && boltIndexEnd > FilmEndOfBoltIndex))
            {
                //无效
                ClearSelected();
                return;
            }

            //有交集，限制范围
            if (boltIndexBegin < FilmBeginOfBoltIndex)
                boltIndexBegin = (int)FilmBeginOfBoltIndex;

            if (boltIndexBegin > FilmEndOfBoltIndex)
                boltIndexBegin = (int)FilmEndOfBoltIndex;

            if (boltIndexEnd < FilmBeginOfBoltIndex)
                boltIndexEnd = (int)FilmBeginOfBoltIndex;

            if (boltIndexEnd > FilmEndOfBoltIndex)
                boltIndexEnd = (int)FilmEndOfBoltIndex;


            SelectedOfBoltIndex = Math.Min(boltIndexBegin, boltIndexEnd);
            SelectedWidthOfBoltIndex = Math.Abs(boltIndexEnd - boltIndexBegin);

            CalSelectedWidth();

        }

        void updateMark() 
        {
            if (IsSelectedValid && SelectedWidthOfBoltIndex == 0)
            {
                if (scanData == null)
                {
                    MarkOfX = NULL_VALUE;
                    MarkOfY = NULL_VALUE;
                }
                else
                {
                    var values = scanData.Thicks;
                    int idx = SelectedOfBoltIndex;
                    if (idx < 0)
                        idx = 0;
                    else if (idx >= values.Count())
                        idx = values.Count() - 1;
                    MarkOfX = idx + 1;
                    MarkOfY = values[idx];
                }
            }
            else {
                MarkOfX = NULL_VALUE;
                MarkOfY = NULL_VALUE;
            }
        }
        
    }
}
