using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Txgy.EWS.Client.FocalMechanism.Model;
using Txgy.Microseismic.BaseLib.Models;
using FmGrid = Txgy.EWS.Client.FocalMechanism.Model.FmGrid;
using FMStation = Txgy.EWS.Client.FocalMechanism.Model.FMStation;

namespace Txgy.EWS.Client.FocalMechanism.Core
{
    /// <summary>
    /// 走滑
    /// </summary>
    public class LineFactory : Factory
    {
        public int firstAngle { get; set; }
        public int lastAngle { get; set; }
        public double?[] distanceArray { get; set; }

        public int angle { get; set; }
        public double maxDis { get; set; }

        public LineFactory(FmGrid g) : base(g)
        {
            this.firstAngle = -1;
            this.lastAngle = -1;
            this.distanceArray = new double?[180];
            angle = -1;
        }
        /// <summary>
        /// 判断是否为走滑
        /// </summary>
        /// <param name="map"></param>
        /// <returns></returns>
        public ComputationResult generateResult(FMMap map)
        {
            ComputationResult result = null;
            Line l = computeLine(map);
            if (l != null)
            {
                result = new ComputationResult();
                result.graph = l;
                result.Direction = l.angle < 90 ? l.angle + 90 : l.angle - 90;
                result.FocalType = FocalMechanismType.strikeSlip;
                map.T = FocalMechanismType.strikeSlip;
            }
            return result;
        }

        private Line computeLine(FMMap map)
        {
            if (map.posStation.Count == 0 || map.negStation.Count == 0)
            {
                return null;
            }
            for (int i = 0; i < 180; i++)
            {
                double posMax = int.MinValue;
                double posMin = int.MaxValue;
                for (int j = 0; j < map.posStation.Count; j++)
                {
                    int fj = grid.StationList.ToList<FMStation>().FindIndex(fi => fi.Name == map.posStation[j]);
                    if (fj==-1) continue;
                    posMax = Math.Max(posMax, grid.distance[i, fj]);
                    posMin = Math.Min(posMin, grid.distance[i, fj]);
                }

                double negMax = int.MinValue;
                double negMin = int.MaxValue;
                for (int j = 0; j < map.negStation.Count; j++)
                {
                    int fj = grid.StationList.ToList<FMStation>().FindIndex(fi => fi.Name == map.negStation[j]);
                    if (fj == -1) continue;
                    negMax = Math.Max(negMax, grid.distance[i, fj]);
                    negMin = Math.Min(negMin, grid.distance[i, fj]);
                }

                if (posMax <= negMin)
                {
                    if (negMin - posMax > maxDis)
                    {
                        maxDis = negMin - posMax;
                        angle = i;
                    }
                    distanceArray[i] = (negMin - posMax) / 2 + posMax;
                }
                if (posMin >= negMax)
                {
                    if (posMin - negMax > maxDis)
                    {
                        maxDis = posMin - negMax;
                        angle = i;
                    }
                    distanceArray[i] = (posMin - negMax) / 2 + negMax;
                }
            }

            //in the case that one of the types only has one point
            if (map.posStation.Count == 1 || map.negStation.Count == 1)
            {
                if (angle == -1 || distanceArray[angle]==null) return null;
                return new Line(angle, (double)distanceArray[angle]);
            }
            return GetMulPoints();
        }

        public Line GetMulPoints()
        {
            for (int i = 1; i < 179; i++)
            {
                if (distanceArray[i] != null && distanceArray[i - 1] == null) firstAngle = i;
                if (distanceArray[i] != null && distanceArray[i + 1] == null) lastAngle = i;
            }
            if (firstAngle < 0 && lastAngle < 0)
                return null;

            if (distanceArray[0] != null && distanceArray[179] == null) firstAngle = 0;
            if (distanceArray[179] != null && distanceArray[0] == null) lastAngle = 179;
            if (firstAngle > lastAngle)
            {
                lastAngle += 180;
            }
            int tempA = (firstAngle + lastAngle) / 2;
            if (tempA >= 180) tempA -= 180;
            if (distanceArray[tempA] == null) return null;

            return new Line(tempA, (double)distanceArray[tempA]);
        }
    }
}
