using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;
using System.Windows.Media.Media3D;
using Txgy.EWS.Client.Models;

namespace Txgy.EWS.Client.Models
{
    public class Plane:BindableBase
    {
        private int id;
        public int ID
        {
            get { return id; }
            set
            {
                SetProperty(ref id, value);
            }
        }

        private Point3D pos1;

        public Point3D Pos1
        {
            get { return pos1; }
            set
            {
                SetProperty(ref pos1, value);
            }
        }
        private Point3D pos2;

        public Point3D Pos2
        {
            get { return pos2; }
            set
            {
                SetProperty(ref pos2, value);
            }
        }
        private Point3D pos3;

        public Point3D Pos3
        {
            get { return pos3; }
            set
            {
                SetProperty(ref pos3, value);
            }
        }

        private GridItemEventResult event1;

        public GridItemEventResult Event1
        {
            get { return event1; }
            set
            {
                SetProperty(ref event1, value);
            }
        }
        private GridItemEventResult event2;

        public GridItemEventResult Event2
        {
            get { return event2; }
            set
            {
                SetProperty(ref event2, value);
            }
        }
        private GridItemEventResult event3;

        public GridItemEventResult Event3
        {
            get { return event3; }
            set
            {
                SetProperty(ref event3, value);
            }
        }
        private bool _valid = true;
        /// <summary>
        /// 有效的
        /// </summary>
        public bool Valid
        {
            get { return _valid; }
            set { _valid = value; }
        }

        /// <summary>
        /// 震源属性
        /// </summary>
        public int focal = 0;

        private List<GridItemEventResult> _inRangeEventList = new List<GridItemEventResult>();
        /// <summary>
        /// 在范围内的事件
        /// </summary>
        public List<GridItemEventResult> InRangeEventList
        {
            get { return _inRangeEventList; }
            set { _inRangeEventList = value; }
        }
        private List<EventFrequency> _eventFrequencyList;
        /// <summary>
        /// 事件频度统计列表
        /// </summary>
        public List<EventFrequency> EventFrequencyList
        {
            get { return _eventFrequencyList; }
            set { _eventFrequencyList = value; }
        }

        private int _lastSameFocal = 0;

        public int LastSameFocal
        {
            get { return _lastSameFocal; }
            set { _lastSameFocal = value; }
        }
        private int _maxUnbrokenSameFocalCount = 0;

        public int MaxUnbrokenSameFocalCount
        {
            get { return _maxUnbrokenSameFocalCount; }
            set { _maxUnbrokenSameFocalCount = value; }
        }


        private int _unbrokenSameFocalCount = 0;

        public int UnbrokenSameFocalCount
        {
            get { return _unbrokenSameFocalCount; }
            set { _unbrokenSameFocalCount = value; }
        }

        private Color _planeColor;

        public Color PlaneColor
        {
            get { return _planeColor; }
            set
            {
                SetProperty(ref _planeColor, value);
            }
        }
        private double mpara;

        public double MPara
        {
            get { return mpara; }
            set
            {
                SetProperty(ref mpara, value);
            }
        }
        private double npara;

        public double NPara
        {
            get { return npara; }
            set
            {
                SetProperty(ref npara, value);
            }
        }
        private double ppara;

        public double PPara
        {
            get { return ppara; }
            set
            {
                SetProperty(ref ppara, value);
            }
        }
        private Point3D crossPoint;

        public Point3D CrossPoint
        {
            get { return crossPoint; }
            set
            {
                SetProperty(ref crossPoint, value);
            }
        }

        public void SetMNPPara()
        {
            MPara = (Pos2.Y - Pos1.Y) * (Pos3.Z - Pos1.Z)
                    - (Pos2.Z - Pos1.Z) * (Pos3.Y - Pos1.Y);
            NPara = (Pos3.X - Pos1.X) * (Pos2.Z - Pos1.Z)
                - (Pos2.X - Pos1.X) * (Pos3.Z - Pos1.Z);
            PPara = (Pos2.X - Pos1.X) * (Pos3.Y - Pos1.Y)
                - (Pos3.X - Pos1.X) * (Pos2.Y - Pos1.Y);
        }
        public void SetCrossPoint(Point3D ep)
        {
            double z = (ep.Z * ((MPara * MPara) / PPara) + ep.Z * ((NPara * NPara) / PPara) + MPara * (Pos1.X - ep.X)
                + NPara * (Pos1.Y - ep.Y) + PPara * Pos1.Z) / ((MPara * MPara) / PPara + (NPara * NPara) / PPara + PPara);
            double x = (z - ep.Z) * (MPara / PPara) + ep.X;
            double y = (z - ep.Z) * (NPara / PPara) + ep.Y;
            CrossPoint = new Point3D(x, y, z);
        }
        public static double GetEvent2CrossDis(Point3D ep, Point3D cp)
        {
            //Debug.WriteLine(ep.ToString());
            //Debug.WriteLine(cp.ToString());
            double dx = Math.Pow(ep.X - cp.X, 2);
            double dy = Math.Pow(ep.Y - cp.Y, 2);
            double dz = Math.Pow(ep.Z - cp.Z, 2);
            double dis = Math.Sqrt(dx + dy + dz);
            return dis;
        }
        /// <summary>
        /// 获取点到平面的距离
        /// </summary>
        /// <param name="eventPos">事件点坐标</param>
        /// <returns>距离</returns>
        public double GetEventToPlaneDistance(Point3D eventPos)
        {
            double z = (eventPos.Z * ((MPara * MPara) / PPara) + eventPos.Z * ((NPara * NPara) / PPara) + MPara * (Pos1.X - eventPos.X)
                + NPara * (Pos1.Y - eventPos.Y) + PPara * Pos1.Z) / ((MPara * MPara) / PPara + (NPara * NPara) / PPara + PPara);
            double x = (z - eventPos.Z) * (MPara / PPara) + eventPos.X;
            double y = (z - eventPos.Z) * (NPara / PPara) + eventPos.Y;
            Point3D cp = new Point3D(x, y, z);
            double dx = Math.Pow(eventPos.X - cp.X, 2);
            double dy = Math.Pow(eventPos.Y - cp.Y, 2);
            double dz = Math.Pow(eventPos.Z - cp.Z, 2);
            double dis = Math.Sqrt(dx + dy + dz);
            return dis;
        }
        /// <summary>
        /// 计算平面与参考平面的夹角
        /// </summary>
        /// <param name="plane">平面</param>
        /// <param name="referencePlane">参考平面</param>
        /// <returns>倾角</returns>
        public static double CalculatePlaneAngle(Plane plane, Point3D referencePlane)
        {
            // 计算平面法向量            
            Point3D normal = CrossProduct(Subtract(plane.Pos2, plane.Pos1), Subtract(plane.Pos3, plane.Pos1));

            // 计算平面法向量与参考平面法向量之间的夹角（单位为度）
            double dotProduct = DotProduct(normal, referencePlane);
            double angle = Math.Acos(dotProduct / (Magnitude(normal) * Magnitude(referencePlane))) * 180 / Math.PI;
            return angle;
        }

        /// <summary>
        /// 向量减法
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static Point3D Subtract(Point3D a, Point3D b)
        {
            Point3D result = new Point3D();
            result.X = a.X - b.X;
            result.Y = a.Y - b.Y;
            result.Z = a.Z - b.Z;
            return result;
        }

        /// <summary>
        /// 向量叉积
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static Point3D CrossProduct(Point3D a, Point3D b)
        {
            Point3D result = new Point3D();
            result.X = a.Y * b.Z - b.Y * a.Z;
            result.Y = a.Z * b.X - a.X * b.Z;
            result.Z = a.X * b.Y - a.Y * b.X;
            return result;
        }

        /// <summary>
        /// 向量点积
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static double DotProduct(Point3D a, Point3D b)
        {
            double result = 0.0;
            result += a.X * b.X;
            result += a.Y * b.Y;
            result += a.Z * b.Z;
            return result;
        }

        /// <summary>
        /// 向量模长
        /// </summary>
        /// <param name="a"></param>
        /// <returns></returns>
        public static double Magnitude(Point3D a)
        {
            double sumOfSquares = 0.0;
            sumOfSquares += a.X * a.X;
            sumOfSquares += a.Y * a.Y;
            sumOfSquares += a.Z * a.Z;
            return Math.Sqrt(sumOfSquares);
        }
    }
    public class EventFrequency
    {
        public DateTime StartTime { get; set; }
        public int Frequency { get; set; } = 0;
    }
}

