using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using DevExpress.XtraEditors;
using DevExpress.Utils;
using SIASUN.Autopilot.GNSS;
using SIASUN.Autopilot.Model;
using ProjectBase.Data.BaseDAL;
using SIASUN.Autopilot.BLL;
using ProjectBase.Data.Redis;
using ProjectBase.Util;
using ProjectBase.Data.Logs;

namespace SIASUN.Autopilot.View
{
    public partial class FormMonitor : DevExpress.XtraEditors.XtraForm
    {
        #region 私有变量
        /// <summary>
        /// 鼠标位置
        /// </summary>
        private Point mousePoint = new Point();   //鼠标位置
        ///// <summary>
        ///// 图片宽度
        ///// </summary>
        //private int ImageWidth;
        ///// <summary>
        ///// 图片高度
        ///// </summary>
        //private int ImageHeight;

        /// <summary>
        /// 坐标与经纬度转换对象
        /// </summary>
        private CoordinateConversion conversion;
        /// <summary>
        /// 行驶过程中的经纬度
        /// </summary>
        private List<PointF> pointDriving = new List<PointF>();

        /// <summary>
        /// 行驶过程中航向角度
        /// </summary>
        private List<float> angleDriving = new List<float>();

        /// <summary>
        /// 线的宽度
        /// </summary>
        private const int lineWidth = 3;    //线的宽度

        /// <summary>
        /// 下拉框选择路径的所有点
        /// </summary>
        private List<MoLocationRuleInfo> locationList = new List<MoLocationRuleInfo>();  //下拉框选择路径

        private Status status = Status.Stop;

        private delegate void startPointMesgDelegate();

        BlDecisionControler control = new BlDecisionControler();

        ///// <summary>
        ///// 状态
        ///// </summary>
        private enum Status
        {
            Play,
            Stop,
        }

        RedisHelper redis = new RedisHelper();
        #endregion

        public FormMonitor()
        {
            InitializeComponent();
            //BeckhoffOpcHelper bfOpc = new BeckhoffOpcHelper();
            //bfOpc.Opc_Init();

        }

        private void FormDeviceManagement_Load(object sender, EventArgs e)
        {
            InitControls();

            MoLocationMap map = BLLFactory<BlLocationMap>.Instance.FindSingle(string.Format("map_id = '{0}'", System.Configuration.ConfigurationManager.AppSettings["MapId"]));
            WGS84Points point0 = new WGS84Points { x = map.LocationLon1,y = map.LocationLat1,z = 0};
            WGS84Points point1 = new WGS84Points { x = map.LocationLon2,y = map.LocationLat2,z = 0};
            PointF imagePoint0 = new PointF { X = map.LocationX1, Y = map.LocationY1};
            PointF imagePoint1 = new PointF { X = map.LocationX2, Y = map.LocationY2};
            conversion = new CoordinateConversion(imagePoint0, imagePoint1, point0, point1);
            BlGNSSPerception.Instance.Init();
            BlGNSSPerception.Instance.GNSSHandler += GetDrivingInfo;
            control.StartPointHandler += StartPointMessage;
            redis.SetString(SysEnvironment.Start,"1");
        }

        /// <summary>
        /// 初始化控件
        /// </summary>
        private void InitControls()
        {
            //测试状态使用，正式使用时需注释掉
            this.layoutControlGroup2.Visibility = DevExpress.XtraLayout.Utils.LayoutVisibility.Never;
            this.layoutControlGroup3.Visibility = DevExpress.XtraLayout.Utils.LayoutVisibility.Never;
            this.layoutControlGroup4.Visibility = DevExpress.XtraLayout.Utils.LayoutVisibility.Never;
            //地图控件
            this.picExControl1.SetImage(global::SIASUN.Autopilot.View.Properties.Resources.地图1, true);
            //ImageWidth = global::SIASUN.Autopilot.View.Properties.Resources.地图1.Width;
            //ImageHeight = global::SIASUN.Autopilot.View.Properties.Resources.地图1.Height;
            this.picExControl1.MouseMoveTooltipEvent += new PicExControl.MouseMoveTooltip(picExControl1_MouseMove);
            this.picExControl1.DrawOriginalPathEvent += new PicExControl.DrawPath(DrawOriginalPath);
            this.picExControl1.DrawDrivingPathEvent += new PicExControl.DrawPath(DrawDrivingPath);

            //下拉框
            this.lookUp_Path.Properties.DataSource = BLLFactory<BlLocationRuleInfo>.Instance.SqlTable("SELECT rule_name FROM location_rule_info GROUP BY rule_name");
            this.lookUp_Path.Properties.ValueMember = "RULE_NAME";
            this.lookUp_Path.Properties.DisplayMember = "RULE_NAME";
            this.lookUp_Path.Properties.NullText = null;

            this.btn_Stop.Enabled = false;
        }

        /// <summary>
        /// 鼠标移动显示经纬度
        /// </summary>
        /// <param name="e"></param>
        private void picExControl1_MouseMove(MouseEventArgs e)
        {
            if (mousePoint.X != e.X || mousePoint.Y != e.Y)
            {
                ToolTipControllerShowEventArgs args = this.toolTip_Message.CreateShowArgs();
                //this.toolTip_Message.SetToolTip(this.picExControl1, string.Format("横坐标:{0}\n纵坐标:{1}", e.X.ToString(), e.Y.ToString()));
                //this.toolTip_Message.SetTitle(this.picExControl1,"提示");
                //this.toolTip_Message.SetToolTipIconType(this.picExControl1,ToolTipIconType.Exclamation);
                double lon;
                double lat;
                conversion.GetGaussToWGS84((e.X - this.picExControl1.StartPoint.X) / this.picExControl1.Wrate, (e.Y - this.picExControl1.StartPoint.Y) / this.picExControl1.Hrate, out lon,out lat);
                args.ToolTip = string.Format("经度:{0}\n纬度:{1}", lon.ToString(), lat.ToString());
                args.SelectedControl = this.picExControl1;
                //args.Title = "提示";
                this.toolTip_Message.ShowHint(args, System.Windows.Forms.Control.MousePosition);
                mousePoint.X = e.X;
                mousePoint.Y = e.Y;
            }
            else
            {
                //this.toolTip1.Hide(this.pictureBox1);
                mousePoint.X = e.X;
                mousePoint.Y = e.Y;
            }
        }

        /// <summary>
        /// 指令信息表格
        /// </summary>
        private void InitGridDirective()
        {
            if (this.lookUp_Path.EditValue != null)
            {
                this.gridControl__Directive.DataSource = BLLFactory<BlActionDirective>.Instance.Find(string.Format("rule_name = '{0}'",SysEnvironment.CurrentRuleName));
                this.gridControl__Directive.RefreshDataSource();
            }

        }

        /// <summary>
        /// 指令信息表格——单元格样式
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void gridView__Directive_RowCellStyle(object sender, DevExpress.XtraGrid.Views.Grid.RowCellStyleEventArgs e)
        {
            if (e.Column.FieldName == "DirectiveResult")
            {
                Color color = Color.White;
                if (Convert.ToInt32(e.CellValue) == 1)
                {
                    e.Appearance.BackColor = Color.Green;
                    e.Appearance.BackColor2 = Color.LightCyan;
                }
                else if (Convert.ToInt32(e.CellValue) == 0)
                {
                    e.Appearance.BackColor = Color.Red;
                    e.Appearance.BackColor2 = Color.LightCyan;
                }
            }
        }

        private void picExControl1_MouseLeave(object sender, EventArgs e)
        {
            this.toolTip_Message.HideHint();
        }

        /// <summary>
        /// 画行驶路径
        /// </summary>
        /// <param name="g"></param>
        private void DrawDrivingPath(Graphics g)
        {
            if (pointDriving.Count < 1 || angleDriving.Count < 1)
            {
                return;
            }
            double x;
            double y;
            if (redis.GetString(SysEnvironment.Start).Equals("1"))     //车辆未到达起始点
            {
                conversion.GetWGS84ToGauss(pointDriving[pointDriving.Count -1].X, pointDriving[pointDriving.Count - 1].Y, out x, out y);
                g.TranslateTransform((float)x, (float)y);
                g.RotateTransform(angleDriving[angleDriving.Count -1]);
                g.DrawImage(global::SIASUN.Autopilot.View.Properties.Resources.汽车2, -7, -15, 14, 30);
                return;
            }
            //车辆到达起始点
            if (pointDriving.Count < 2)
            {
                conversion.GetWGS84ToGauss(pointDriving[0].X, pointDriving[0].Y, out x, out y);
                g.TranslateTransform((float)x, (float)y);
                g.RotateTransform(angleDriving[0]);
                g.DrawImage(global::SIASUN.Autopilot.View.Properties.Resources.汽车2, -7, -15, 14, 30);
            }
            else
            {
                List<PointF> list = new List<PointF>();
                for (int i = 0; i < pointDriving.Count; i++)
                {
                    conversion.GetWGS84ToGauss(pointDriving[i].X, pointDriving[i].Y, out x, out y);
                    list.Add(new PointF((float)(x * this.picExControl1.Wrate) + this.picExControl1.StartPoint.X, (float)(y * this.picExControl1.Hrate) + this.picExControl1.StartPoint.Y));
                }
                g.DrawCurve(new Pen(Color.Blue, lineWidth), list.ToArray());

                g.TranslateTransform(list[list.Count - 1].X, list[list.Count - 1].Y);
                g.RotateTransform(angleDriving[angleDriving.Count - 1]);
                g.DrawImage(global::SIASUN.Autopilot.View.Properties.Resources.汽车2, -7, -15, 14, 30);
            }

        }

        /// <summary>
        /// 获取行驶中经纬度和角度值
        /// </summary>
        private void GetDrivingInfo(object sender,GNSSInfoEventArgs gnss)
        {
            pointDriving.Add(new PointF { X = (float)gnss.Nmea.gprmc.Longitude, Y = (float)gnss.Nmea.gprmc.Latitude });
            angleDriving.Add((float)gnss.Nmea.gprmc.Deviated);
            this.picExControl1.Invalidate();
        }

        /// <summary>
        /// 画原始路径
        /// </summary>
        /// <param name="g"></param>
        private void DrawOriginalPath(Graphics g)
        {
            try
            {
                if (locationList.Count <= 0)
                {
                    return;
                }
                List<PointF> list = new List<PointF>();
                double x;
                double y;
                foreach (MoLocationRuleInfo item in locationList)
                {
                    conversion.GetWGS84ToGauss(item.LocationLon, item.LocationLat, out x, out y);
                    list.Add(new PointF((float)(x * this.picExControl1.Wrate) + this.picExControl1.StartPoint.X, (float)(y * this.picExControl1.Hrate) + this.picExControl1.StartPoint.Y));
                }
                g.DrawCurve(new Pen(Color.Red, lineWidth), list.ToArray());
                g.DrawImage(global::SIASUN.Autopilot.View.Properties.Resources.绿色, list[0].X, list[0].Y, 23, 31);
                g.DrawImage(global::SIASUN.Autopilot.View.Properties.Resources.红色, list[list.Count - 1].X, list[list.Count - 1].Y, 23, 31);
            }
            catch (Exception ex)
            {
                DevExpress.XtraEditors.XtraMessageBox.Show("绘制路径失败。" + ex.ToString(), "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                LogHelper.log.Error(string.Format("绘制路径失败：{0}", ex.ToString()));
            }

        }

        /// <summary>
        /// 下拉框选中项改变事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void lookUp_Path_EditValueChanged(object sender, EventArgs e)
        {
            try
            {
                if (this.lookUp_Path.EditValue == null)
                {
                    locationList = new List<MoLocationRuleInfo>();
                }
                else
                {
                    SysEnvironment.CurrentRuleName = this.lookUp_Path.EditValue.ToString().Trim();
                    string condition = string.Format("rule_name = '{0}'", this.lookUp_Path.EditValue.ToString());
                    locationList = BLLFactory<BlLocationRuleInfo>.Instance.Find(condition);
                    control.InitPlanRoute(); ;
                }
                this.picExControl1.Invalidate();
                InitGridDirective();
            }
            catch (Exception ex)
            {
                DevExpress.XtraEditors.XtraMessageBox.Show("获取路径失败。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                LogHelper.log.Error(string.Format("获取路径失败：{0}", ex.ToString()));
            }
        }

        /// <summary>
        /// 下拉框按钮点击事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void lookUp_Path_ButtonClick(object sender, DevExpress.XtraEditors.Controls.ButtonPressedEventArgs e)
        {
            if (e.Button.Kind == DevExpress.XtraEditors.Controls.ButtonPredefines.Delete)
            {
                LookUpEdit lookUp = sender as LookUpEdit;
                lookUp.EditValue = null;

            }
        }

        /// <summary>
        /// 停止按钮事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_Stop_Click(object sender, EventArgs e)
        {
            if (status != Status.Play)
            {
                return;
            }
            //redis.SetString(SysEnvironment.Start, "0");
            this.btn_Stop.Enabled = false;
            this.btn_Action.Enabled = true;
            status = Status.Stop;
            pointDriving.Clear();
            angleDriving.Clear();
        }

        /// <summary>
        /// 窗口关闭事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FormDeviceManagement_FormClosing(object sender, FormClosingEventArgs e)
        {
            BlGNSSPerception.Instance.Close();
        }

        /// <summary>
        /// 开始按钮事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_Action_Click(object sender, EventArgs e)
        {
            if (status != Status.Stop)
            {
                return;
            }
            if (this.lookUp_Path.EditValue == null)
            {
                DevExpress.XtraEditors.XtraMessageBox.Show("请选择路径之后再开始测试", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
            //redis.SetString(SysEnvironment.Start,"1");
            this.btn_Action.Enabled = false;
            status = Status.Play;
            this.btn_Stop.Enabled = true;
            pointDriving.Clear();
            angleDriving.Clear();

        }


        /// <summary>
        /// 指令信息表格——显示文字
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void gridView__Directive_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e)
        {
            if (e.Column.FieldName == "DirectiveResult")
            {
                if (Convert.ToInt32(e.Value) == 0)
                {
                    e.DisplayText = "失败";
                }
                else if (Convert.ToInt32(e.Value) == 1)
                {
                    e.DisplayText = "成功";
                }
                else if (Convert.ToInt32(e.Value) == 2)
                {
                    e.DisplayText = "未执行";
                }
            }
        }

        //private void InitGridControl()
        //{
        //    //OpcFactory.Instance.opcHelper.GetOpcRecv();
        //    EventMessages.Instance.newMessages += Instance_newMessages;
        //}

        //private void Instance_newMessages(object sender, EventMessage.MessageEventArgs e)
        //{
        //    throw new NotImplementedException();
        //}

        /// <summary>
        /// 响应起始点正确事件的函数
        /// </summary>
        /// <param name="e"></param>
        private void StartPointMessage(object sender, StartPointEventArgs e)
        {
            DevExpress.XtraEditors.XtraMessageBox.Show(e.Mesg, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
            //control.StartPointHandler -= StartPointMessage;
            ////BlGNSSPerception.Instance.Close();
            //if (this.btn_Stop.InvokeRequired)
            //{
            //    startPointMesgDelegate mesgDelegate = new startPointMesgDelegate(StopCommunicate);
            //    this.btn_Stop.BeginInvoke(mesgDelegate, null);
            //}
        }

        /// <summary>
        /// 放大按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_Big_Click(object sender, EventArgs e)
        {
            float rate = 1;
            if (Math.Max(this.picExControl1.Wrate, this.picExControl1.Hrate) <= 10)
            {
                rate = 1.15F;
            }
            Zoom(rate);
        }

        /// <summary>
        /// 缩小按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_Small_Click(object sender, EventArgs e)
        {
            float rate = 1;
            if (Math.Min(this.picExControl1.Wrate, this.picExControl1.Hrate) > Math.Max(0.75687, 0.75687))
            {
                rate = 0.85F;
            }
            Zoom(rate);
        }

        /// <summary>
        /// 地图缩放
        /// </summary>
        /// <param name="rate"></param>
        private void Zoom(float rate)
        {
            if (rate == 1) return;
            float imageX = (356F - this.picExControl1.StartPoint.X) / this.picExControl1.Wrate;
            float imageY = (279F - this.picExControl1.StartPoint.Y) / this.picExControl1.Hrate;

            this.picExControl1.Hrate *= rate;
            this.picExControl1.Wrate *= rate;

            this.picExControl1.StartPoint = new PointF(356F - imageX * this.picExControl1.Wrate, 279F - imageY * this.picExControl1.Hrate);
            this.picExControl1.Invalidate();
        }
    }
}