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

namespace FLY.Simulation
{
    public class CurveCollection : Misc.ISaveToXml
    {
        public static string EXT_NAME = ".curve";
        public static string DEFAULT_FILE = "default" + EXT_NAME;

        #region 数据文件需要保存的数据项
        public class Curve : Misc.ISaveToXml, INotifyPropertyChanged
        {
            private int _value;
            /// <summary>
            /// 面密度
            /// </summary>
            public int Value
            {
                get { return _value; }
                set
                {
                    _value = value;
                    NotifyPropertyChanged("Value");
                }
            }
            private int _ad;

            public int AD
            {
                get { return _ad; }
                set
                {
                    _ad = value;
                    NotifyPropertyChanged("AD");
                }
            }

            private int _revisedAD;
            /// <summary>
            /// 校正后的AD值
            /// </summary>
            public int RevisedAD
            {
                get { return _revisedAD; }
                set
                {
                    _revisedAD = value;
                    NotifyPropertyChanged("RevisedAD");
                }
            }

            #region ISaveToXml 成员

            public string[] GetSavePropertyNames()
            {
                return new string[]{
                    "Value",
                    "AD"};
            }

            #endregion

            #region INotifyPropertyChanged 成员
            protected void NotifyPropertyChanged(string propertyName)
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
                }
            }
            public event PropertyChangedEventHandler PropertyChanged;

            #endregion
        }
        public class ExChange : Misc.ISaveToXml
        {
            public int OrgAD { get; set; }
            public int CurrAD { get; set; }

            public string[] GetSavePropertyNames()
            {
                return new string[]{
                    "OrgAD",
                    "CurrAD"};
            }
        }

        /// <summary>
        /// 输入的曲线
        /// </summary>
        private ObservableCollection<Curve> mCurves = new ObservableCollection<Curve>();
        public ObservableCollection<Curve> Curves
        {
            get
            {
                return mCurves;
            }
        }
        #endregion

        /// <summary>
        /// 真实样品校正点
        /// </summary>
        private ObservableCollection<ExChange> mRevisingCurves = new ObservableCollection<ExChange>();
        public ObservableCollection<ExChange> RevisingCurves
        {
            get
            {
                return mRevisingCurves;
            }
        }
        public CurveCollection()
        {
            Misc.SaveToXmlHepler.Regist(typeof(Curve));
            Misc.SaveToXmlHepler.Regist(typeof(ExChange));

            //Curves.Add(new Curve() { AD = 57564, Value = 0 });
            //Curves.Add(new Curve() { AD = 30850, Value = 8800 });
            //Curves.Add(new Curve() { AD = 19000, Value = 17600 });
            //Curves.Add(new Curve() { AD = 12528, Value = 26400 });
            //Curves.Add(new Curve() { AD = 8409, Value = 35200 });
            //Curves.Add(new Curve() { AD = 5650, Value = 44000 });
            //Curves.Add(new Curve() { AD = 3779, Value = 52800 });
            //Curves.Add(new Curve() { AD = 2513, Value = 61600 });
            //Curves.Add(new Curve() { AD = 1660, Value = 70400 });


            Curves.Add(new Curve() { Value = 0, AD = 50300 });
            Curves.Add(new Curve() { Value = 1900, AD= 46505});
            Curves.Add(new Curve() { Value = 3800, AD=42999});
            Curves.Add(new Curve() { Value = 5800, AD=39698});
            Curves.Add(new Curve() { Value = 7800, AD=36646});
            Curves.Add(new Curve() { Value = 9800, AD=33894});
            Curves.Add(new Curve() { Value = 11800, AD=31229});
            Curves.Add(new Curve() { Value = 13700, AD=28934});
            Curves.Add(new Curve() { Value = 15600, AD=26818});
            Curves.Add(new Curve() { Value = 17500, AD=24908});
            Curves.Add(new Curve() { Value = 19400, AD=23220});
            Curves.Add(new Curve() { Value = 21300, AD=21558});
            Curves.Add(new Curve() { Value = 23200, AD=20057});
            Curves.Add(new Curve() { Value = 25100, AD=18606});
            Curves.Add(new Curve() { Value = 27100, AD=17283});
            Curves.Add(new Curve() { Value = 29000, AD = 16035 });

            //foreach (Curve c in Curves) 
            //{
            //    c.AD = (int)(c.AD * 58881.0 / 50300);
            //}

           
        }

        public void Clear()
        {
            Curves.Clear();
            ClearExChange();
        }
        #region CURVE
        //ad值从大到小排列
        public void ModifyPoint(int ad, int value)
        {
            var cs = from c in Curves where c.AD == ad select c;
            if (cs.Count() > 0)
            {
                cs.First().Value = value;
            }
            else
            {
                Curves.Add(new Curve() { AD = ad, Value = value });
                Curves.OrderByDescending(c => c.AD);
            }
        }
        public bool DeletePoint(int ad)
        {
            var cs = from c in Curves where c.AD == ad select c;
            if (cs.Count() > 0)
            {
                Curves.Remove(cs.First());
                return true;
            }
            return false;
        }
        #endregion
        #region ExChange

        public void ModifyExChange(int org_ad, int curr_ad)
        {
            //index=0 zero, index=1 sample
            var cs = from c in RevisingCurves where c.OrgAD == org_ad select c;
            if (cs.Count() > 0)
            {
                cs.First().CurrAD = curr_ad;
            }
            else
            {
                RevisingCurves.Add(new ExChange() { OrgAD = org_ad, CurrAD = curr_ad });
                RevisingCurves.OrderByDescending(c => c.OrgAD);
            }
        }
        public void ClearExChange()
        {
            RevisingCurves.Clear();
        }
        #endregion


        public static bool CheckRevisingPointValid(int ad)
        {
            if (ad < 3)
            {
                return false;
            }
            else
            {
                return true;
            }
        }

        public bool ReviseCurve()
        {
            if (RevisingCurves.Count < 1)//没数据
            {
                foreach (Curve c in Curves)
                {
                    c.RevisedAD = c.AD;
                }
                return false;
            }

            if (RevisingCurves.Count == 1)//只有一个校正点
            {
                double ux = ((double)RevisingCurves[0].CurrAD) / RevisingCurves[0].OrgAD;

                foreach (Curve c in Curves)
                {
                    c.RevisedAD = (int)(c.AD * ux);
                }
                return true;
            }
            else
            {
                int adh = RevisingCurves[0].OrgAD;
                int adl = RevisingCurves[1].OrgAD;
                double uh = ((double)RevisingCurves[0].CurrAD) / adh;
                double ul = ((double)RevisingCurves[1].CurrAD) / adl;

                //int k;
                for (int i = 0; i < Curves.Count; i++)
                {
                    //k = j;
                    //while ((m_curves[i].Value > m_revisingCurves[j].Value) && (j < m_revisingCurves.Count - 1)) j++;
                    //if (k != j)
                    //{
                    //    adh = m_revisingCurves[j-1].OrgAD;
                    //    adl = m_revisingCurves[j].OrgAD;
                    //    uh = ((double)m_revisingCurves[j-1].CurrAD) / adh;
                    //    ul = ((double)m_revisingCurves[j].CurrAD) / adl;
                    //}
                    double ux = uh - (adh - Curves[i].AD) * (uh - ul) / (adh - adl);

                    Curves[i].RevisedAD = (int)(Curves[i].AD * ux);
                }

                return true;
            }
        }

        public int Value2AD(int value, AD2ValueFlag flag)
        {
            int n = Curves.Count;
            int i;
            int ad;
            double tmp, tmp1;

            if (Curves.Count <= 0)
                return Misc.MyBase.NULL_VALUE;

            if (value <= Curves[0].Value) i = 1;
            for (i = 1; i < n; i++)
            {
                if (value > Curves[i].Value) continue;
                else break;
            }
            if (i >= n) i = n - 1;
            tmp = (double)(Curves[i - 1].Value - value) / (Curves[i].Value - Curves[i - 1].Value);

            if (flag == AD2ValueFlag.NoRevised)
            {
                tmp1 = (double)Curves[i - 1].AD / Curves[i].AD;
                ad = (int)(Curves[i - 1].AD * Math.Exp(tmp * Math.Log(tmp1, Math.E)));
            }
            else
            {
                tmp1 = (double)Curves[i - 1].RevisedAD / Curves[i].RevisedAD;
                ad = (int)(Curves[i - 1].RevisedAD * Math.Exp(tmp * Math.Log(tmp1, Math.E)));
            }
            return ad;
        }
        public enum AD2ValueFlag
        {
            /// <summary>
            /// 修正后的曲线
            /// </summary>
            Revised,
            /// <summary>
            /// 原始曲线
            /// </summary>
            NoRevised
        }
        public int AD2Value(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 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 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);

            }
            return thick;
        }

        public int GetZeroAD()
        {
            if (RevisingCurves.Count < 1)
                return Curves[0].AD;
            else
                return Curves[0].RevisedAD;
        }


        bool IsCurveFile(string file)
        {
            if (file.Length < EXT_NAME.Length) return false;

            if (file.Substring(file.Length - EXT_NAME.Length).CompareTo(EXT_NAME) == 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }


        #region ISaveToXml 成员

        public string[] GetSavePropertyNames()
        {
            return new string[]{
                "Curves"};
        }

        #endregion
    }
}
