using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using cn.edu.suda.sumcu.iot.chart;
using System.Windows.Forms.DataVisualization.Charting;

//Form类主要针对MainForm.应用开发，故放在cn.edu.suda.sumcu.MainForm.空间下的form子空间中
namespace cn.edu.suda.sumcu.iot.form
{
    public partial class FrmHistorySeries : Form
    {

        private FrmMain frmMain; //声明要继承的窗体 
        private int rowCount;    //显示表单的当前位置
        private DataTable dt;    //最新查询到的表单
        //声明绘图区,在一个绘图区上绘制多条曲线
        private ChartArea chartArea = new ChartArea("chartArea");
        //声明图线，可实例化多条曲线  
        private List<Series> series = new List<Series>();
        //实例化DrawSeries类
        private DrawSeries draw;      
        //声明存储Y轴最大值的全局数组
        private List<double> maxData_MCUtemp = new List<double>();
        //声明存储Y轴最大值的全局数组
        private List<double> maxData_SignalPower = new List<double>();

        public FrmHistorySeries()
        {
            InitializeComponent();
        }

        public FrmHistorySeries(FrmMain frm_Main)
            : this()
        {
            this.frmMain = frm_Main;
        }

        /// ===========================================================
        /// <summary>                                                       
        /// 函 数 名:FrmHistorySeries_Load：历史数据曲线页面加载函数                              
        /// 功    能:完成历史数据曲线页面的初始化工作                                                                  
        /// </summary>                                                      
        /// ===========================================================
        private void FrmHistorySeries_Load(object sender, EventArgs e)
        {
            //（1）添加“选择查询的IMSI号”列表的内容
            //用于存储监听的IMSI个数
            int count = 0;
            //对于g_IMSI数组中的每个IMSI号            
            foreach (string Imsi in frmMain.g_IMSI) 
            {
                //清除字符串开始和结尾的空格、tab和换行
                string one_imsi = Imsi.Trim();
                //IMSI号长度为15时
                if (one_imsi.Length == 15)          
                {
                    //添加到监听IMSI列表中
                    ComboBoxSearchIMSI.Items.Add(one_imsi);  
                    count++; //IMSI号个数加1                
                }
            }
            //（2）默认首先显示第一个IMSI号的曲线
            ComboBoxSearchIMSI.SelectedIndex = 0;
            //（3）默认清空标签
            LabelFrmHisNum.Text = "";
            //（4）初始化窗口时，将chart控件的图例去掉
            chart1.Legends.Clear();
            //（5）鼠标移到数据点时显示数据
            chart1.GetToolTipText += new EventHandler<ToolTipEventArgs>(chart1_GetToolTipText);
        }

        /// ===========================================================
        /// <summary>
        /// 函数名称：BtnSearch_Click                                        
        /// 函数功能：点击查询，根据IMSI号查询日期获得图表信息
        /// </summary>
        /// ===========================================================
        private void BtnSearch_Click(object sender, EventArgs e)
        {
            //查询起始时间，这里使用的是日期控件
            string startTime = dateTimePicker_Start.Text.Trim();
            //查询结束时间
            string endTime = dateTimePicker_End.Text.Trim();
            //获取选中的IMSI号
            string imsi = ComboBoxSearchIMSI.SelectedItem.ToString();

            //错误提示
            if (Convert.ToDateTime(startTime) > DateTime.Now)
            {
                errorProvider1.SetError(dateTimePicker_Start, "日期必须小于或等于当前系统日期！");
                return;
            }
            else
            {
                errorProvider1.Clear();
                if (Convert.ToDateTime(endTime) > DateTime.Now)
                {
                    errorProvider1.SetError(dateTimePicker_End, "日期必须小于或等于当前系统日期！");
                    return;
                }
                else
                {
                    errorProvider1.Clear();
                    if (Convert.ToDateTime(startTime) >= Convert.ToDateTime(endTime))
                    {
                        errorProvider1.SetError(dateTimePicker_Start, "起始日期必须小于或等于结束日期！");
                        return;
                    }
                    else
                    {
                        errorProvider1.Clear();
                        bindData(startTime, endTime, imsi);
                    }
                }
            }
        }

        /// ===========================================================
        /// <summary>                                                       
        /// 函数名称：bindData                                     
        /// 传入参数：time1：时间控件的起始时间
        ///           time2：时间控件的终止时间
        ///           imsi：选中的imsi号                                     
        /// 函数返回：无      
        /// 函数功能：根据选择的IMSI号利用dt绑定Frame表中需要的数据列，
        /// 并生成相应曲线
        /// </summary>                                                                                          
        /// ===========================================================
        private void bindData(string time1, string time2, string imsi)
        {
            //根据选中的IMSI号获取相应的dt
            dt = frmMain.sQLUp.selectNeed("IMSI", imsi);

            //将起始时间time1转化为DateTime型的时间
            DateTime d1 = Convert.ToDateTime(time1);
            //将结束时间time2转化为DateTime型的时间
            DateTime d2 = Convert.ToDateTime(time2);

            //获取时间基准
            System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1));
            ulong temp1 = (ulong)(d1.AddHours(8) - startTime).TotalSeconds;
            ulong temp2 = (ulong)(d2.AddHours(8) - startTime).TotalSeconds;

            //求出满足要求的点的个数
            rowCount = 0;
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                ulong temp = Convert.ToUInt64(dt.Rows[i]["currentTime"].ToString());
                if ((temp >= temp1) && (temp <= temp2))
                {
                    rowCount++;
                }
            }

            //声明存放接收时间的数组（c#格式时间）
            DateTime[] sendTime = new DateTime[rowCount];
            //声明存放MCU温度的数组
            double[] MCUtmp = new double[rowCount];
            //声明存放信号强度的数组
            double[] signalPower = new double[rowCount];

            rowCount = 0;
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                ulong temp = Convert.ToUInt64(dt.Rows[i]["currentTime"].ToString());
                if ((temp >= temp1) && (temp <= temp2))
                {
                    //将时间戳转换成c#格式的时间
                    sendTime[rowCount] = StampToDateTime(dt.Rows[i]["currentTime"].ToString());
                    MCUtmp[rowCount] = Convert.ToDouble(Convert.ToDouble(dt.Rows[i]["mcuTemp"].ToString()) / 10);
                    signalPower[rowCount] = Convert.ToDouble(Convert.ToInt32(dt.Rows[i]["signalPower"].ToString()));
                    rowCount++;
                }
            }

            //根据选择的IMSI号显示label中的内容
            LabelFrmHisNum.Text = ComboBoxSearchIMSI.SelectedItem.ToString()
                + "的帧数为：" + rowCount.ToString();

            //开始绘图
            //初始化chart控件并清空曲线中数据点的数据
            draw = new DrawSeries(chart1, chartArea);

            ////设置X轴的显示
            ////入口参数检查
            if (rowCount == 0)
            {
                //帧数为0时：不显示图线，Label中会显示帧数为0
                chart1.ChartAreas.Clear();
                chart1.Series.Clear();
                chart1.Legends.Clear();
                return;
            }
            else if (rowCount <= 5)
            {
                //帧数为小于或等于5时：显示点，Label显示当前数据帧数
                //调用draw的hisSeriesInit（）方法（显示数据点）
                draw.hisSeriesInit(chart1, chartArea, series, 0, sendTime, MCUtmp, "MCU温度", "blue", getMax_MCUtemp(MCUtmp));
                //调用draw的hisSeriesInit（）方法（显示数据点）
                draw.hisSeriesInit(chart1, chartArea, series, 0, sendTime, signalPower, "信号强度", "green", getMax_SignalPower(signalPower));
            }
            else
            {
                //帧数大于5时：显示图线，Label中会显示相应帧数
                //调用draw的hisSeriesInit（）方法（显示曲线）
                draw.hisSeriesInit(chart1, chartArea, series, sendTime, MCUtmp, "MCU温度", "blue", getMax_MCUtemp(MCUtmp));
                //调用draw的hisSeriesInit（）方法（显示曲线）
                draw.hisSeriesInit(chart1, chartArea, series, sendTime, signalPower, "信号强度", "green", getMax_SignalPower(signalPower));
            }
        }

        /// ===========================================================
        /// <summary>
        /// 方法名称：getMax_MCUtemp
        /// 输入参数：data[]存放测试数据的数组
        /// 方法返回：获取MCUtemp数组中的最大值
        ///  </summary>
        /// ===========================================================
        private double getMax_MCUtemp(double[] data)
        {
            double max = data[0];
            for (int i = 1; i < data.Length; i++)
            {
                if (data[i] > max)
                {
                    max = data[i];
                }
            }
            maxData_MCUtemp.Add(max);
            return max;
        }

        /// ===========================================================
        /// <summary>
        /// 方法名称：getMax_SignalPower
        /// 输入参数：data[]存放测试数据的数组
        /// 方法返回：获取SignalPower数组中的最大值
        ///  </summary>
        /// ===========================================================
        private double getMax_SignalPower(double[] data)
        {
            double max = data[0];
            for (int i = 1; i < data.Length; i++)
            {
                if (data[i] > max)
                {
                    max = data[i];
                }
            }
            maxData_SignalPower.Add(max);
            return max;
        }

        

        /// ===========================================================
        /// <summary>                                                       
        /// 函数名称：StampToDateTime                                     
        /// 传入参数：timeStamp：时间戳                                                 
        /// 函数返回：dateTimeStart：转换之后的时间      
        /// 函数功能：时间戳转为C#格式时间 
        /// </summary>                                                                                          
        /// ===========================================================
        private DateTime StampToDateTime(string timeStamp)
        {
            DateTime dateTimeStart = new DateTime(1970, 1, 1);
            long lTime = long.Parse(timeStamp + "0000000");
            TimeSpan toNow = new TimeSpan(lTime);
            return dateTimeStart.Add(toNow);
        }

        /// ===========================================================
        /// <summary>                                                       
        /// 函数名称：chart1_GetToolTipText                                           
        /// 函数功能：chart控件中自带的方法：
        ///           判断鼠标是否移动到数据标记点，是则显示提示信息
        /// </summary>                                                                                          
        /// ===========================================================
        private void chart1_GetToolTipText(object sender, ToolTipEventArgs e)
        {
            ////判断鼠标是否移动到数据标记点，是则显示提示信息
            if (e.HitTestResult.ChartElementType == ChartElementType.DataPoint)
            {
                //移至数据点时显示十字光标
                this.Cursor = Cursors.Cross;
                //获取命中数据点的索引
                int i = e.HitTestResult.PointIndex;
                //根据索引获取选择的点的X、Y轴的值
                DataPoint dp = e.HitTestResult.Series.Points[i];
                //将double的xvalue转换为datetime形式 
                DateTime dt = DateTime.FromOADate(dp.XValue);

                //获取曲线的索引值
                int j = chart1.Series.IndexOf(e.HitTestResult.Series);
                if (j == 0)
                {
                    //如果为第一条曲线
                    //分别显示x和y轴的数值，其中{1:F1}精确到小数点后1位
                    e.Text = string.Format("{0}\nMCU温度:{1:F1} ", dt, dp.YValues[0] *
                                    maxData_MCUtemp[maxData_MCUtemp.Count() - 1]);                
                }
                else
                {
                    //如果为第二条曲线
                    //分别显示x和y轴的数值    
                    e.Text = string.Format("{0}\n信号强度:{1} ", dt, dp.YValues[0] *
                                    maxData_SignalPower[maxData_SignalPower.Count() - 1]);
                }
            }
            else
            {
                this.Cursor = Cursors.Default;
            }
        }
    }
}