using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Windows.Forms.DataVisualization.Charting;
using System.IO;
using System.Threading;
using System.Reflection;

using FLY.Thick.Base.IService;
using FLY.Thick.Base.Client;
using FLY.Thick.Base.Common;
using FObjBase;
using FLY.UI.Module;

namespace ThickTcpUiInWindow.UIModule
{
    /// <summary>
    /// Page_Fix.xaml 的交互逻辑
    /// </summary>
    public partial class FixGraph : Page, INotifyPropertyChanged
    {
        FixGraphItemParam graphparam;

        FixService mFixService;
        DynArea mDynArea;
        FixGraphManager mFixGraphManager;
        //FLY.UI.Module.IAnalyzePage mAnalyzePage=null;

        private bool hasAnalyze = false;
        public bool HasAnalyze 
        {
            get { return hasAnalyze; }
            set
            {
                if (hasAnalyze != value)
                {
                    hasAnalyze = value;
                    NotifyPropertyChanged("HasAnalyze");
                }
            }
        }

        public FixGraph()
        {
            InitializeComponent();
            InitializeComponent2();
            mFixGraphManager = new FixGraphManager();
            stackpanel_state.DataContext = mFixGraphManager;
            button_analyze.DataContext = this;


        }

        public void Init(int id)
        {
            graphparam = FixGraphParams.Current.Items.Find(p => p.ID == id);
            if (graphparam == null)
            {
                graphparam = new FixGraphItemParam() { ID = id };
                FixGraphParams.Current.Items.Add(graphparam);
                FixGraphParams.Current.Save();
            }

            //获取设备
            TDGage gage = Application.Current.Properties["Gage"] as TDGage;

            //if (!string.IsNullOrEmpty(graphparam.AnalyzeModule))
            //{
            //    if (lmodule.PageModules.Keys.Contains(graphparam.AnalyzeModule))
            //    {
            //        if (lmodule.PageModules[graphparam.AnalyzeModule] is FLY.UI.Module.IAnalyzePage)
            //        {
            //            graphparam.mAnalyze = lmodule.PageModules[graphparam.AnalyzeModule] as FLY.UI.Module.IAnalyzePage;
            //        }
            //    }
            //}
            
            mFixService = gage.mFixService;
            mDynArea = gage.mDynAreaService.mDynArea;

            run_title.DataContext = graphparam;
            run_title2.DataContext = mFixGraphManager;

            mFixGraphManager.Init(mFixService, graphparam, chart1.Series[0].Points);

            mDynArea.PropertyChanged += new PropertyChangedEventHandler(mDynArea_PropertyChanged);

            graphparam.PropertyChanged += new PropertyChangedEventHandler(graphparam_PropertyChanged);

            mFixGraphManager.PropertyChanged += new PropertyChangedEventHandler(mFixGraphManager_PropertyChanged);


            //if (bulkGraphItemFix.mAnalyze != null)
            //{
            //    HasAnalyze = true;
            //    mAnalyzePage = bulkGraphItemFix.mAnalyze;
            //}
            //else
            //{
                HasAnalyze = false;
            //    mAnalyzePage = null;
            //}
            
        }

        void mFixGraphManager_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "AutoTarget")
            {
                if(graphparam.IsAutoTarget)
                    UpdateAxisY();
            }
            else if (e.PropertyName == "CalState")
            {
                UpdateDataCalRange();
            }
        }

        void graphparam_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "IsAutoTarget")
            {
                UpdateAxisY();
            }
            else if (e.PropertyName == "Interval")
            {

                //清空全部数据
                mFixGraphManager.Clear();
                UpdateXRange();
            }
            else if (e.PropertyName == "Len")
            {

                //全部数据  mDatas -> mPoints
                mFixGraphManager.Clear();
                UpdateXRange();
            }
        }

        void InitializeComponent2()
        {
            System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea1 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
            System.Windows.Forms.DataVisualization.Charting.Series series1 = new System.Windows.Forms.DataVisualization.Charting.Series();


            // 
            // chart1
            // 
            chart1.Name = "chart1";
            chart1.BackColor = System.Drawing.Color.Transparent;


            chartArea1.Name = "Default";

            //chartArea1.BackColor = this.chart1.BackColor;
            //chartArea1.BackColor = System.Drawing.Color.Transparent;
            //chartArea1.BackColor = System.Drawing.Color.OldLace;
            //chartArea1.BackGradientStyle = System.Windows.Forms.DataVisualization.Charting.GradientStyle.TopBottom;
            //chartArea1.BackSecondaryColor = System.Drawing.Color.White;
            chartArea1.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
            chartArea1.BorderDashStyle = System.Windows.Forms.DataVisualization.Charting.ChartDashStyle.Solid;

            chartArea1.AxisX.LabelStyle.Font = new System.Drawing.Font("Trebuchet MS", 8.25F, System.Drawing.FontStyle.Bold);
            chartArea1.AxisX.LineColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
            chartArea1.AxisX.MajorGrid.LineColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
            chartArea1.AxisX.IsMarksNextToAxis = false;
            //chartArea1.AxisX.Interval = 5;

            chartArea1.AxisY.LabelStyle.Font = new System.Drawing.Font("Trebuchet MS", 8.25F, System.Drawing.FontStyle.Bold);
            chartArea1.AxisY.LineColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
            chartArea1.AxisY.MajorGrid.LineColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));


            //chartArea1.Position.Height = 100;// 42F;
            //chartArea1.Position.Width = 100;// 88F;
            //chartArea1.Position.X = 0;// 3F;
            //chartArea1.Position.Y = 0;// 10F;

            //chartArea1.ShadowColor = System.Drawing.Color.Transparent;
            this.chart1.ChartAreas.Add(chartArea1);



            series1.Name = "Series 1";
            series1.ChartArea = "Default";
            series1.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(180)))), ((int)(((byte)(26)))), ((int)(((byte)(59)))), ((int)(((byte)(105)))));
            series1.BorderWidth = 4;


            //TODO
            series1.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
            series1.Color = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(65)))), ((int)(((byte)(140)))), ((int)(((byte)(240)))));

            //series1.MarkerStyle = System.Windows.Forms.DataVisualization.Charting.MarkerStyle.Circle;

            series1.ShadowColor = System.Drawing.Color.Black;
            series1.ShadowOffset = 2;

            series1.XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.Int32;
            series1.YValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.Double;


            chart1.Series.Add(series1);
        }

        /// <summary>
        /// 获取实际应用的目标值，公差
        /// </summary>
        /// <param name="target"></param>
        /// <param name="alarm"></param>
        /// <param name="ispercent"></param>
        void GetActualTargetAlarm(out double target, out double alarm, out bool ispercent)
        {
            double multi = 100.0;
            if (graphparam.IsAutoTarget)
                target = mFixGraphManager.AutoTarget / multi;//AutoTarget 计算得到的平均值
            else
                target = mDynArea.Target / multi;

            ispercent = graphparam.IsPercent;
            if ((ispercent) && (mDynArea.Target <= 0) || (mDynArea.Alarm < 0) || (target <= 0))
                ispercent = false;

            if (ispercent)
            {
                alarm = target * mDynArea.Alarm / mDynArea.Target;
            }
            else
            {
                alarm = mDynArea.Alarm / multi;
            }

            if (alarm < 0.1)
                alarm = 0.1;
        }
        /// <summary>
        /// 与 Multi,Target,YRange,Alarm 相关
        /// </summary>
        void UpdateAxisY()
        {

            double alarm;
            double target;
            bool ispercent;
            GetActualTargetAlarm(out target, out alarm, out ispercent);

            System.Windows.Forms.DataVisualization.Charting.Axis axisY = chart1.ChartAreas["Default"].AxisY;

            //TODO
            axisY.Crossing = target;

            // Set manual minimum and maximum values.
            axisY.Minimum = target - alarm * 3;
            axisY.Maximum = target + alarm * 3;

            axisY.CustomLabels.Clear();

            SetCustomLabel(axisY, target, GridTickTypes.All, System.Drawing.Color.Green, ispercent, null);

            SetCustomLabel(axisY, target + alarm, GridTickTypes.All, System.Drawing.Color.DarkRed, ispercent, null);
            SetCustomLabel(axisY, target - alarm, GridTickTypes.All, System.Drawing.Color.DarkRed, ispercent, null);

            SetCustomLabel(axisY, target + alarm * 2, GridTickTypes.All, System.Drawing.Color.Red, ispercent, null);
            SetCustomLabel(axisY, target - alarm * 2, GridTickTypes.All, System.Drawing.Color.Red, ispercent, null);

            SetCustomLabel(axisY, axisY.Minimum, GridTickTypes.TickMark, System.Drawing.Color.Black, ispercent, null);
            SetCustomLabel(axisY, axisY.Maximum, GridTickTypes.TickMark, System.Drawing.Color.Black, ispercent, null);

        }
        
        void UpdateDataCalRange()
        {
            Axis axisX = chart1.ChartAreas["Default"].AxisX;
            axisX.Title = mFixGraphManager.CalState;
        }

        void UpdateXRange()
        {
            // Set manual minimum and maximum values.
            Axis axisX = chart1.ChartAreas["Default"].AxisX;
            axisX.CustomLabels.Clear();
            axisX.Minimum = 0;
            if (graphparam.Len <= 2000)
                axisX.Maximum = graphparam.Len;
            else 
                axisX.Maximum = 2000;

            double interval_ms =graphparam.Interval;
            if (interval_ms < 10)
                interval_ms *= 1.28;

            double total_r = graphparam.Len * interval_ms / 1000;
            double total_s = axisX.Maximum - axisX.Minimum;
           
            //设置自定义X轴
            SetCustomLabel(axisX, axisX.Minimum, "0s");
            SetCustomLabel(axisX, axisX.Minimum + total_s*1/5, (total_r*1/5).ToString("F1")+"s");
            SetCustomLabel(axisX, axisX.Minimum + total_s * 2 / 5, (total_r * 2 / 5).ToString("F1") + "s");
            SetCustomLabel(axisX, axisX.Minimum + total_s * 3 / 5, (total_r * 3 / 5).ToString("F1") + "s");
            SetCustomLabel(axisX, axisX.Minimum + total_s * 4 / 5, (total_r * 4 / 5).ToString("F1") + "s");
            SetCustomLabel(axisX, axisX.Maximum, (total_r).ToString("F1") + "s");
        }

        void SetCustomLabel(Axis axis, double p, string text)
        {
            double r = axis.Maximum - axis.Minimum;
            double f, t;
            f = p + r / 6;
            t = p - r / 6;
            axis.CustomLabels.Add(f, t, text,0, LabelMarkStyle.None, GridTickTypes.All);
        }
        void SetCustomLabel(Axis axisY, double p, GridTickTypes gt, System.Drawing.Color c, bool ispercent, string message)
        {
            double r = axisY.Maximum - axisY.Minimum;
            double f, t;
            f = p + r / 2;
            t = p - r / 2;
            double target = (axisY.Maximum + axisY.Minimum) / 2;

            CustomLabel customLabel;
            string str;
            if (!ispercent)
            {
                str = p.ToString("N1");

            }
            else
            {
                if (target == p)
                {
                    str = p.ToString("N1");
                }
                else
                {
                    double percent;

                    percent = ((p - target) / target) * 100;
                    str = percent.ToString("N1") + "%";
                }
            }
            if (!string.IsNullOrEmpty(message))
                str = message + " " + str;

            customLabel = axisY.CustomLabels.Add(f, t, str);

            customLabel.GridTicks = gt;
            customLabel.ForeColor = c;
        }
        void mDynArea_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if ((e.PropertyName == "Target") ||
                (e.PropertyName == "Alarm"))
            {

                UpdateAxisY();
            }
        }
        private void button_info_Click(object sender, RoutedEventArgs e)
        {
            FixGraphConfig w = new FixGraphConfig();
            w.Init(graphparam);
            w.Owner = FLY.ControlLibrary.COMMON.GetWindow(this);
            w.ShowDialog();
        }
        private void button_save_Click(object sender, RoutedEventArgs e)
        {
            mFixGraphManager.PreSave();
            Window_SaveDatas w = new Window_SaveDatas();
            w.Init(mFixGraphManager);
            w.ShowDialog();
        }
        private void Page_Loaded(object sender, RoutedEventArgs e)
        {
            UpdateXRange();
            UpdateAxisY();
            UpdateDataCalRange();
        }

        private void Page_Unloaded(object sender, RoutedEventArgs e)
        {

        }

        private void button_pause_Click(object sender, RoutedEventArgs e)
        {

            mFixGraphManager.IsPaused = !mFixGraphManager.IsPaused;
        }
        #region INotifyPropertyChanged 成员

        public event PropertyChangedEventHandler PropertyChanged;
        protected void NotifyPropertyChanged(string propertyname)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyname));
            }
        }
        #endregion

        private void button_analyze_Click(object sender, RoutedEventArgs e)
        {
            //if (mAnalyzePage != null)
            //{
            //    TimeSpan ts;
            //    double v = mDynArea.FilmVelocity;
            //    double[] datas = mFixGraphManager.GetData(out ts);
            //    mAnalyzePage.Show(datas, ts, v);
            //}
        }
    }

    public class FixGraphManager : ISaveManager, INotifyPropertyChanged 
    {
        FixService mFixService;
        public FixGraphItemParam graphparam;
        DataPointCollection mPoints;
        List<double> mDatas = new List<double>();
 
        private string savepath;
        public string SavePath
        {
            get { return savepath; }
            set
            {
                if (savepath != value)
                {
                    savepath = value;
                    NotifyPropertyChanged("SavePath");
                }
            }
        }
        
        private int autoTaget;
        public int AutoTarget
        {
            get
            {
                return autoTaget;
            }
            set
            {
                if (autoTaget != value)
                {
                    autoTaget = value;
                    NotifyPropertyChanged("AutoTarget");
                }
            }
        }
        private string state;
        public string State
        {
            get { return state; }
            set
            {
                if (state != value)
                {
                    state = value;
                    NotifyPropertyChanged("State");
                }
            }
        }
        private string calstate = "Max:null Min:null Avg:null 2σ:null";
        public string CalState
        {
            get { return calstate; }
            set
            {
                if (calstate != value)
                {
                    calstate = value;
                    NotifyPropertyChanged("CalState");
                }
            }
        }
        private bool isPaused = false;
        public bool IsPaused
        {
            get { return isPaused; }
            set
            {
                if (isPaused != value)
                {
                    isPaused = value;
                    NotifyPropertyChanged("IsPaused");
                }
            }
        }

        double Avg;
        double Max;
        double Min;
        double Sigma;


        public void Init(FixService fixService, FixGraphItemParam bulkGraphItemFix, DataPointCollection points)
        {
            mFixService = fixService;
            graphparam = bulkGraphItemFix;
            mPoints = points;

            mFixService.RegistTimeGridEvent(new TimeGridEventHandler(mFixService_TimeGridEvent));
        }
        public void Clear() 
        {
            mDatas.Clear();
            mPoints.Clear();
            data3.Clear();
            temp.Clear();
            data3_totaltime = TimeSpan.Zero;
        }
        #region 用于间隔
        List<double> temp = new List<double>();//mDatas->mPoints 的转换
        List<int> data3 = new List<int>();
        TimeSpan data3_totaltime = TimeSpan.Zero;
        #endregion
        #region 用于混合
        List<int> data4 = new List<int>();
        #endregion
        void mFixService_TimeGridEvent(object sender, TimeGridEventArgs e)
        {
            double multi = 100.0;

            if (IsPaused)
                return;

            if (graphparam.Interval < 1)//最短1.28ms
                graphparam.Interval = 1;
            else if (graphparam.Interval > 3000)//最长3s
                graphparam.Interval = 3000;

            if (graphparam.Mix < 1)
                graphparam.Mix = 1;
            else if (graphparam.Mix > 100)
                graphparam.Mix = 100;

            if (graphparam.Len < 100)
                graphparam.Len = 100;
            else if (graphparam.Len > 50000)
                graphparam.Len = 50000;



            List<double> data2 = new List<double>();
            TimeSpan interval;
            if (graphparam.Interval < 10)
                interval = TimeSpan.FromTicks((long)(graphparam.Interval * TimeSpan.TicksPerMillisecond * 1.28));
            else
                interval = TimeSpan.FromTicks((long)(graphparam.Interval * TimeSpan.TicksPerMillisecond));

            for (int i = 0; i < e.data.Length; i++)
            {
                data3.Add(e.data[i]);
                data3_totaltime += e.ts;
                int avg = Misc.MyBase.NULL_VALUE;
                
                if (data3_totaltime >= interval)
                {
                    avg = Misc.MyMath.Avg(data3.ToArray());
                    data3.Clear();
                    data3_totaltime -= interval;
                    if (Misc.MyBase.ISVALIDATA(avg))
                    {
                        data4.Add(avg);
                        while (data4.Count > graphparam.Mix)
                            data4.RemoveAt(0);
                        data2.Add(data4.Average() / multi);
                    }
                }
            }
            if (data2.Count() > 0)
            {
                State = e.time.ToString("HH:mm:ss") + " / ";
                if (graphparam.Interval >= 10)
                    State = e.time.ToString("HH:mm:ss") + " / " + interval.TotalMilliseconds.ToString("F0") + "ms";
                else
                    State = e.time.ToString("HH:mm:ss") + " / " + (graphparam.Interval * 1.28).ToString() + "ms";

                AddPoint(data2);
            }
        }


        void AddPoint(List<double> data)
        {
            foreach (double d in data)
                mDatas.Add(d);
            

            //删除数据
            if (mDatas.Count > graphparam.Len) 
                mDatas.RemoveRange(0, mDatas.Count - graphparam.Len);

            //更新状态
            AutoTarget = (int)(data.Average() * 100.0);

            Max = mDatas.Max();
            Min = mDatas.Min();
            Avg = mDatas.Average();
            double sum = mDatas.Sum(p => Math.Pow((p - Avg), 2));
            double cnt = mDatas.Count();
            Sigma = Math.Sqrt(sum / (cnt - 1));

            CalState = "Max:" + Max.ToString("F1") +
                " Min:" + Min.ToString("F1") +
                " Avg:" + Avg.ToString("F1") +
                " 2σ:" + (Sigma * 2).ToString("F1");


            //显示在屏幕的数据，只能有2000个
            if (graphparam.Len <= 2000)
            {
                foreach (double d in data)
                    mPoints.Add(d);
                while (mPoints.Count > graphparam.Len)
                    mPoints.RemoveAt(0);
            }
            else
            {
                int scale = graphparam.Len / 2000;//肯定是整数倍
                foreach (double d in data)
                {
                    temp.Add(d);
                    if (temp.Count >= scale)
                    {
                        mPoints.Add(temp.Average());
                        temp.Clear();
                    }
                }
                //删除数据
                while (mPoints.Count > 2000)
                    mPoints.RemoveAt(0);
            }

        }

        public void PreSave() 
        {
            string directory = System.IO.Path.GetDirectoryName(SavePath);
            if(string.IsNullOrEmpty(directory))
            {
                directory = "C:";
            }

            SavePath = directory + @"\" + DateTime.Now.ToString("yyyyMMdd_HHmmss") + ".csv";
        }

        AsyncCBHandler mAsyncDelegate;
        object mAsyncState;
        /// <summary>
        /// 成功或失败，会调用 AsyncDelegate
        /// </summary>
        /// <param name="AsyncDelegate"></param>
        /// <param name="AsyncState"></param>
        public void Save(AsyncCBHandler AsyncDelegate, object AsyncState)
        {
            //需要异步！！！！
            if (!IsPaused)
            {
                mAsyncDelegate(mAsyncState, false);
                return;
            }
            mAsyncDelegate = AsyncDelegate;
            mAsyncState = AsyncState;
            Thread t = new Thread(Output);
            t.Start();
        }
        void Output()
        {
            string path = SavePath;
            try
            {
                using (StreamWriter sw = new StreamWriter(path, false, Encoding.GetEncoding("GB2312")))
                {
                    double ms = graphparam.Interval;
                    if (ms < 10)
                        ms *= 1.28;
                    double t = 0;
                    sw.WriteLine("时间(ms),数据");
                    foreach (double d in mDatas)
                    {
                        sw.WriteLine(t.ToString("F1")+","+d.ToString("F1"));
                        t += ms;
                    }
                    sw.Flush();
                    sw.Close();
                }
                mAsyncDelegate(mAsyncState, true);
            }
            catch(Exception e)
            {
                mAsyncDelegate(mAsyncState, false);
            }
        }
        public double[] GetData(out TimeSpan interval) 
        {
            double[] datas = mDatas.ToArray();
            long ticks;
            if (graphparam.Interval < 10)
                ticks = (long)(graphparam.Interval * 1.28 * TimeSpan.TicksPerMillisecond);
            else
                ticks = graphparam.Interval * TimeSpan.TicksPerMillisecond;
            interval = TimeSpan.FromTicks(ticks);

            return datas;
        }
        #region INotifyPropertyChanged 成员

        public event PropertyChangedEventHandler PropertyChanged;
        protected void NotifyPropertyChanged(string propertyname)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyname));
            }
        }
        #endregion
    }

    public class AnaylzeButtonVisibilityConverter : IMultiValueConverter
    {
        #region IMultiValueConverter 成员

        public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if ((values.Length == 2) && (values[0] is bool) && (values[1] is bool))//必须要检查，不然 界面生成器 会错误，提示转换异常
            {
                bool b1 = (bool)values[1];
                bool b2 = (bool)values[0];
                if (b1 && b2)
                    return Visibility.Visible;
                else
                    return Visibility.Hidden;
            }
            else
            {
                return Visibility.Hidden;
            }
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
        {
            return null;
        }

        #endregion
    }


    /// <summary>
    /// 
    /// </summary>
    public class FixGraphItemParam: UIModuleParam
    {
        private int len = 120;
        public int Len
        {
            get { return len; }
            set
            {
                if (len != value)
                {
                    len = value;
                    NotifyPropertyChanged("Len");
                }
            }
        }

        private int interval = 1000;
        /// <summary>
        /// 间隔，只能选 1, 10, 100, 1000, 这些单位；
        /// 特别的，1 = 1.28ms，10=10ms，100=100ms
        /// </summary>
        public int Interval
        {
            get { return interval; }
            set
            {
                if (interval != value)
                {
                    interval = value;
                    NotifyPropertyChanged("Interval");
                }
            }
        }


        private int mix = 3;
        public int Mix
        {
            get
            {
                return mix;
            }
            set
            {
                if (mix != value)
                {
                    mix = value;
                    NotifyPropertyChanged("Mix");
                }
            }
        }


        private bool isautotarget = false;
        public bool IsAutoTarget
        {
            get
            {
                return isautotarget;
            }
            set
            {
                if (isautotarget != value)
                {
                    isautotarget = value;
                    NotifyPropertyChanged("IsAutoTarget");
                }
            }
        }

        private bool ispercent = false;
        public bool IsPercent
        {
            get
            {
                return ispercent;
            }
            set
            {
                if (ispercent != value)
                {
                    ispercent = value;
                    NotifyPropertyChanged("IsPercent");
                }
            }
        }

        public void CopyTo(FixGraphItemParam dest)
        {
            dest.ID = ID;
            dest.Len = Len;
            dest.Interval = Interval;
            dest.Mix = Mix;
            dest.IsAutoTarget = IsAutoTarget;
            dest.IsPercent = IsPercent;
        }





        public override string[] GetSavePropertyNames()
        {
            List<string> names = new List<string>(base.GetSavePropertyNames());
            names.AddRange(new string[]{
                "Len",
                "Interval",
                "Mix",
                "IsAutoTarget",
                "IsPercent"
            });
            return names.ToArray();
        }
    }

    /// <summary>
    /// 全部扫描图的参数
    /// </summary>
    public class FixGraphParams : UIModuleParams<FixGraphItemParam>
    {

        static FixGraphParams()
        {
            Misc.SaveToXmlHepler.Regist(typeof(FixGraphParams));
        }
        public FixGraphParams()
        {
            string path = System.IO.Path.Combine(FLYLayout.BasePath, "fixgraph.xml");
            FilePath = path;
        }
        static FixGraphParams current = null;
        public static FixGraphParams Current
        {
            get
            {
                if (current == null)
                {
                    current = new FixGraphParams();
                    current.Load();
                }
                return current;
            }
        }
    }

    /// <summary>
    /// 扫描图控件模块
    /// </summary>
    public class UIModule_FixGraph : IUIModule
    {
        /// <summary>
        /// 控件标题
        /// 它的值取决于culture
        /// </summary>
        public string Title
        {
            get
            {
                return Application.Current.FindResource("strFixGraph") as string;
            }
        }

        /// <summary>
        /// 控件
        /// 创建时，需要给它唯一ID，让加载自己的数据
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public FrameworkElement GetComponent(int id)
        {
            FixGraph graph = new FixGraph();
            graph.Init(id);
            return graph;
        }

        /// <summary>
        /// 控件缩略图，用于编辑界面时，大致看看
        /// 创建时，需要给它唯一ID，让加载自己的数据
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public FrameworkElement GetThumbnail(int id)
        {
            return new System.Windows.Controls.Grid();
        }


        /// <summary>
        /// 给出全部控件ID, 控件自行删除没有的参数
        /// </summary>
        /// <param name="IDs"></param>
        public void MatchParam(int[] IDs)
        {
            FixGraphParams.Current.MatchParam(IDs);
        }
    }
}