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
    {
        const int NULL_VALUE = -100000;



        #region 界面统计值

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

        /// <summary>
        /// 膜结束位置 单位:分区序号
        /// </summary>
        public double FilmEndOfBoltIndex { get; set; } = NULL_VALUE;

        /// <summary>
        /// 选择的位置 单位:分区序号
        /// </summary>
        public double SelectedOfBoltIndex { get; set; } = NULL_VALUE;

        /// <summary>
        /// 选择的位置宽度 单位:分区序号
        /// </summary>
        public double SelectedWidthOfBoltIndex { get; set; } = 0;

        /// <summary>
        /// 选择范围宽度 mm
        /// </summary>
        public int SelectedWidthMm { get; set; } = -1;

        /// <summary>
        /// 选择点 有效
        /// </summary>
        public bool IsSelectedValid => SelectedOfBoltIndex >= 0;
        #endregion

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

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

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

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

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

            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)
            {
                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;
            }
            else {
                double selectedMm = BoltIndex2Mm(SelectedOfBoltIndex);
                double endMm = BoltIndex2Mm(SelectedOfBoltIndex + SelectedWidthOfBoltIndex);
                SelectedWidthMm = (int)Math.Abs(endMm - selectedMm);
            }
        }
        
        public void SetSelected(double boltIndexBegin, double boltIndexEnd) 
        {
            //当没有数据时，不能选择
            if (!IsMmValid)
                return;


            if ((boltIndexBegin < FilmBeginOfBoltIndex && boltIndexEnd < FilmBeginOfBoltIndex) 
                || (boltIndexBegin > FilmEndOfBoltIndex && boltIndexEnd > FilmEndOfBoltIndex))
            {
                //无效
                SelectedOfBoltIndex = NULL_VALUE;
                SelectedWidthOfBoltIndex = 0;
                CalSelectedWidth();
                return;
            }

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

            if (boltIndexBegin > FilmEndOfBoltIndex)
                boltIndexBegin = FilmEndOfBoltIndex;

            if (boltIndexEnd < FilmBeginOfBoltIndex)
                boltIndexEnd = FilmBeginOfBoltIndex;

            if (boltIndexEnd > FilmEndOfBoltIndex)
                boltIndexEnd = FilmEndOfBoltIndex;


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

            CalSelectedWidth();
        }

        
    }
}
