using FLY.Thick.Base.Common;
using FLY.Thick.Base.Server;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FLY.Simulation.Battery.RayLaser
{
    public class GageAd_Ray : ISimulationGageAD
    {
        CurveCollection curve;

        /// 编码器2 mm/p 胶轮周长200mm,编码器 转1圈800脉冲 正确应该0.25
        /// </summary>
        const double Mmpp2 = 0.24925;

        /// <summary>
        /// 编码器1 mm/p
        /// </summary>
        public double Mmpp { get; set; } = 0.2;

        public double VSignOffset { get; set; }
        public double SensorWidth { get; set; } = 25;
        /// <summary>
        /// 长度为 SensorWidth 的卷积核
        /// </summary>
        public List<double> Conv { get; private set; }

        public int TotalLength { get; private set; }

        GageAd gageAd;
        public GageAd_Ray()
        {

        }
        public void Init(GageAd gageAd) {
            this.gageAd = gageAd;
            curve = gageAd.curve_ray;
            VSignOffset = gageAd.VSignOffsetRay;
            TotalLength = gageAd.TotalLength;
            updateConv();
        }
        void updateConv() {
            List<double> conv = new List<double>();
            //用圆形代替
            double sensorRadius = SensorWidth / 2.0;
            for (int i = 0; i < SensorWidth; i++) {
                double r = Math.Abs(-sensorRadius + i);
                double h = Math.Sqrt(Math.Pow(sensorRadius, 2) - Math.Pow(r, 2));
                conv.Add(h * 2);
            }
            double sum = conv.Sum();
            conv = conv.Select(v => v / sum).ToList();
            Conv = conv;
        }

        int GetAdMm(int mm, int mm_v_offset) {
            int posLength = (int)(gageAd.FilmPosition*1000 - VSignOffset+ mm_v_offset);
            double value = gageAd.GetValue(true, mm, posLength, out GageAd.PosType posType);
            
            if (posType == GageAd.PosType.Hold)
            {
                return 0;
            }

            int ad = curve.Value2Ad(value, AD2ValueFlag.NoRevised);
            if (ad > 65535)
                ad = 65535;
            else if (ad < 0)
                ad = 0;


            return ad;
        }

        Random random = new Random();
        public int GetAD(int mm)
        {
            //需要对探头直径范围的数据求均值
            double hValue = 0;
            for (int i = 0; i < Conv.Count(); i++)
            {
                int mm2 = (int)(mm - Conv.Count()/2.0 + i);
                hValue += GetAdMm(mm2, 0) * Conv[i];
            }

            double vValue = 0;
            for (int i = 0; i < Conv.Count(); i++)
            {
                int mm_v_offset = (int)(-Conv.Count() / 2.0 + i);
                vValue += GetAdMm(mm, mm_v_offset) * Conv[i];
            }

            int ad = (int)((hValue + vValue) / 2);
            return ad;
        }

        public void OnPoll(DateTime now)
        {
            //不实现
            gageAd.OnPoll(now);
        }

        public UInt16 GetInput()
        {
            UInt16 istatus = 0x0fff;

            if (gageAd.IsVSignLight)
                Misc.MyBase.CLEARBIT(ref istatus, IODefinition.IN_VSENSOR);

            if(gageAd.IsSyncLight)
                Misc.MyBase.CLEARBIT(ref istatus, IODefinition.IN_SYNC);
            return istatus;
        }
        public void SetOutput(UInt16 output) {
            if (!Misc.MyBase.CHECKBIT(output, IODefinition.OUT_SYNC))
                gageAd.IsSyncLight = true;
            else
                gageAd.IsSyncLight = false;
        }
        public int GetPosition2()
        {
            return (int)(gageAd.FilmPosition * 1000 / Mmpp2);

        }
        public int GetSpeed2()
        {
            return (int)(gageAd.FilmVelocity * 1000 / 60 / Mmpp2);
        }
    }
}