using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using System.ComponentModel;

using FObjBase;
using FLY.Thick.Base.IService;
using FLY.Thick.Base.Common;
using FLY.Thick.Base.OBJ_INTERFACE;

namespace FLY.Thick.Base.Client
{
    /// <summary>
    /// AD 曲线服务 客户端代理
    /// </summary>
    public class CurveServiceClient : FObjServiceClient, ICurveService
    {
        /// <summary>
        /// AD 曲线服务 客户端代理
        /// </summary>
        /// <param name="id"></param>
        public CurveServiceClient(UInt32 id) : base(id) { }

        /// <summary>
        /// AD 曲线服务 客户端代理
        /// </summary>
        /// <param name="serviceId">服务id</param>
        /// <param name="connName">连接器</param>
        public CurveServiceClient(UInt32 serviceId, string connName) : base(serviceId, connName) { }

        #region ICurveService 成员
        /// <summary>
        /// AD曲线校正方式
        /// </summary>
        public CurveCorrectWay CorrectWay { get; set; }

        public CurveType Flag { get; set; }

        [PropertyChanged.DoNotCheckEquality]
        public List<CurveCell> Curves { get; set; }
        public void SetRevised()
        {
            for (int i = 0; i < Curves.Count(); i++)
            {
                Curves[i].AD = Curves[i].RevisedAD;
            }
        }
        public void Apply()
        {
            Curves.OrderBy(c => c.Value);

            var p = new CURVE_OBJ_INTERFACE.Pack_CurveList();
            p.list = Curves;
            p.flag = Flag;
            p.correctway = CorrectWay;
            string json = Newtonsoft.Json.JsonConvert.SerializeObject(p);

            CurrObjSys.SetValueEx(
               mConn, mServerID, ID,
               CURVE_OBJ_INTERFACE.SET_CURVELIST,
               Misc.Converter.StringToBytes(json)
               );
        }

        #region E

        int AD2Value_E(int ad, AD2ValueFlag flag)
        {
            int i;
            int thick;

            if (Curves.Count < 1) return -1;
            if (ad < 0) return -1;
            if (ad == 0) ad = 1;
            if (flag == AD2ValueFlag.NoRevised)
            {
                for (i = 0; i < Curves.Count; i++)
                {
                    if (ad < Curves[i].AD)
                        continue;
                    else
                        break;
                }
            }
            else
            {
                for (i = 0; i < Curves.Count; i++)
                {
                    if (ad < Curves[i].RevisedAD)
                        continue;
                    else
                        break;
                }
            }
            if (i >= Curves.Count) i = Curves.Count - 1;

            if (i == 0) i = 1;
            if (flag == AD2ValueFlag.NoRevised)
            {

                double adi_ad0 = Math.Log(Curves[i].AD) - Math.Log(Curves[i - 1].AD);
                double vi_v0 = Curves[i].Value - Curves[i - 1].Value;
                double a = vi_v0 / adi_ad0;
                double b = Curves[i - 1].Value - Math.Log(Curves[i - 1].AD) * a;

                thick = (int)(Math.Log(ad) * a + b);

                //double u;
                //u = Math.Log((double)Curves[i - 1].AD / Curves[i].AD, Math.E) * 100 / (Curves[i].Value - Curves[i - 1].Value);
                //thick = (int)(Math.Log((double)Curves[i - 1].AD / ad, Math.E) * 100 / u + Curves[i - 1].Value);
            }
            else
            {
                double adi_ad0 = Math.Log(Curves[i].RevisedAD) - Math.Log(Curves[i - 1].RevisedAD);
                double vi_v0 = Curves[i].Value - Curves[i - 1].Value;
                double a = vi_v0 / adi_ad0;
                double b = Curves[i - 1].Value - Math.Log(Curves[i - 1].RevisedAD) * a;

                thick = (int)(Math.Log(ad) * a + b);

                //double u;

                //u = Math.Log((double)Curves[i - 1].RevisedAD / Curves[i].RevisedAD, Math.E) * 100 / (Curves[i].Value - Curves[i - 1].Value);
                //thick = (int)(Math.Log((double)Curves[i - 1].RevisedAD / ad, Math.E) * 100 / u + Curves[i - 1].Value);

            }
            //if (thick < 0)
            //    return 0;

            return thick;
        }
        #endregion
        #region 线性
        int AD2Value_Line(int ad, AD2ValueFlag flag)
        {
            int i;
            int thick;

            if (Curves.Count < 2) return -1;
            if (ad < 0) return -1;
            if (ad == 0) ad = 1;
            bool isDescending = true;//降序排列
            if (Curves[0].AD < Curves[1].AD)
                isDescending = false;
            //找 ad0<ad<adi

            if (flag == AD2ValueFlag.NoRevised)
            {
                if (isDescending)//降序排列
                {
                    for (i = 0; i < Curves.Count; i++)
                    {
                        if (ad < Curves[i].AD)
                            continue;
                        else
                            break;
                    }
                }
                else
                {
                    for (i = 0; i < Curves.Count; i++)
                    {
                        if (ad > Curves[i].AD)
                            continue;
                        else
                            break;
                    }
                }
                if (i >= Curves.Count) i = Curves.Count - 1;
                if (i == 0) i = 1;

                double adi_ad0 = Curves[i].AD - Curves[i - 1].AD;
                double vi_v0 = Curves[i].Value - Curves[i - 1].Value;
                double a = vi_v0 / adi_ad0;
                double b = Curves[i - 1].Value - Curves[i - 1].AD * a;

                thick = (int)(ad * a + b);
                return thick;
            }
            else
            {
                if (isDescending)//降序排列
                {
                    for (i = 0; i < Curves.Count; i++)
                    {
                        if (ad < Curves[i].RevisedAD)
                            continue;
                        else
                            break;
                    }
                }
                else
                {
                    for (i = 0; i < Curves.Count; i++)
                    {
                        if (ad > Curves[i].RevisedAD)
                            continue;
                        else
                            break;
                    }
                }
                if (i >= Curves.Count) i = Curves.Count - 1;
                if (i == 0) i = 1;

                double adi_ad0 = Curves[i].AD - Curves[i - 1].RevisedAD;
                double vi_v0 = Curves[i].Value - Curves[i - 1].Value;
                double a = vi_v0 / adi_ad0;
                double b = Curves[i - 1].Value - Curves[i - 1].RevisedAD * a;

                thick = (int)(ad * a + b);
                return thick;
            }
        }
        #endregion

        public int AD2Value(int ad, AD2ValueFlag flag)
        {
            switch (Flag)
            {
                case CurveType.Line:
                    return AD2Value_Line(ad, flag);
                default:
                    return AD2Value_E(ad, flag);
            }
        }
        #endregion


        public override void ConnectNotify(IFConn from)
        {
            base.ConnectNotify(from);
            if (from.IsConnected)
            {
                CurrObjSys.SenseConfigEx(
                    mConn, mServerID, ID, 0xffffffff, SENSE_CONFIG.ADD);
                CurrObjSys.GetValueEx(
                    mConn, mServerID, ID,
                    CURVE_OBJ_INTERFACE.GET_CURVELIST);
            }
        }
        public override void PushGetValue(IFConn from, uint srcid, ushort memid, byte[] infodata)
        {
            PushInfo(from, srcid, memid, infodata);
        }
        public override void PushInfo(IFConn from, uint srcid, ushort infoid, byte[] infodata)
        {
            switch (infoid)
            {
                case CURVE_OBJ_INTERFACE.PUSH_CURVELIST:
                    {
                        string json = Misc.Converter.BytesToString(infodata);
                        var p = Newtonsoft.Json.JsonConvert.DeserializeObject<CURVE_OBJ_INTERFACE.Pack_CurveList>(json);
                        CorrectWay = p.correctway;
                        Flag = p.flag;
                        Curves = p.list;
                    } break;
            }
        }
    }
}
