using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace DW5S.KxcApi
{
    /// 
    /// 星历推算帮助类.该类调用了Tle2XYZ.exe进程
    /// 
    public static class EphHelper
    {
        private static readonly DateTime dtZero = new DateTime(1970, 1, 1, 0, 0, 0, 0);
        private const string dll = @"AddIns\星历推算\Tle2XYZ.dll";//此dll已加密
        #region cpp dll Interop 
        [DllImport(dll, EntryPoint = "GenerateXYZByPeriod", CallingConvention = CallingConvention.Cdecl)]
        private extern static void GenerateXYZByPeriod(string line1, string line2, long startTime, int period, int count, double[] res);
        #endregion
        /// 
        /// 推算双行星历
        /// 
        /// 双行根数
        /// 指定时刻(UTC)
        /// 
        public static SatEphCore Calc(string tleStr, DateTime utcTime)
        {
            if (string.IsNullOrWhiteSpace(dll))
                throw new Exception($"找不到{dll}");
            tleStr = tleStr.Replace(";", ";");
            var line1 = tleStr.Split(';')[0];
            var line2 = tleStr.Split(';')[1];
            var timeSpan = (long)(utcTime - dtZero).TotalSeconds;
            double[] res = new double[6];
            GenerateXYZByPeriod(line1, line2, timeSpan, 1, 1, res);
            int satIdD = Convert.ToInt32(line2.Split(" ".ToArray(), StringSplitOptions.RemoveEmptyEntries)[1]);
            string timeStr = line1.Split(" ".ToArray(), StringSplitOptions.RemoveEmptyEntries)[3];
            //24078.27199282
            int year = Convert.ToInt32("20" + timeStr.Substring(0, 2));
            double days = Convert.ToDouble(timeStr.Substring(2));
            DateTime tleTime = new DateTime(year, 1, 1, 0, 0, 0);
            tleTime = tleTime.AddDays(days);
            var dto= new SatEphCore()
            {
                SatId = satIdD,
                SatTime = utcTime,
                TleTime = tleTime,
                X = Math.Round(res[0], 4),
                Y = Math.Round(res[1], 4),
                Z = Math.Round(res[2], 4),
                VX = Math.Round(res[3], 4),
                VY = Math.Round(res[4], 4),
                VZ = Math.Round(res[5], 4),
            };
            dto.Lon = Math.Round(PhysicsHelper.EcefToGeo((dto.X, dto.Y, dto.Z)).lon, 1);
            return dto;
        }
        /// 
        /// 批量推算双行星历
        /// 
        /// 双行根数
        /// 起始时刻(UTC)
        /// 结束(UTC)
        /// 推算间隔(秒)
        /// 
        public static List CalcMult(string tleStr, DateTime startUtc, DateTime endUtc, int spanSeconds)
        {
            if (string.IsNullOrWhiteSpace(dll))
                throw new Exception($"找不到{dll}");
            tleStr = tleStr.Replace(";", ";");
            if (tleStr.EndsWith(";"))
                tleStr = tleStr.Substring(0, tleStr.Length - 1);
            tleStr = tleStr.Replace(";", ";");
            var line1 = tleStr.Split(';')[0];
            var line2 = tleStr.Split(';')[1];
            var timeSpan = (long)(startUtc - dtZero).TotalSeconds;
            var c = (int)((endUtc - startUtc).TotalSeconds / spanSeconds + 1);
            double[] res = new double[6 * c];
            GenerateXYZByPeriod(line1, line2, timeSpan, spanSeconds, c, res);
            int satIdD = Convert.ToInt32(line2.Split(" ".ToArray(), StringSplitOptions.RemoveEmptyEntries)[1]);
            string timeStr = line1.Split(" ".ToArray(), StringSplitOptions.RemoveEmptyEntries)[3];
            //24078.27199282
            int year = Convert.ToInt32("20" + timeStr.Substring(0, 2));
            double days = Convert.ToDouble(timeStr.Substring(2));
            DateTime tleTime = new DateTime(year, 1, 1, 0, 0, 0);
            tleTime = tleTime.AddDays(days);
            var list = new List();
            for (int i = 0; i < res.Length; i += 6)
            {
                var dto = new SatEphCore()
                {
                    SatId = satIdD,
                    SatTime = startUtc.AddSeconds(i / 6 * spanSeconds),
                    TleTime = tleTime,
                    X = Math.Round(res[i], 4),
                    Y = Math.Round(res[i + 1], 4),
                    Z = Math.Round(res[i + 2], 4),
                    VX = Math.Round(res[i + 3], 4),
                    VY = Math.Round(res[i + 4], 4),
                    VZ = Math.Round(res[i + 5], 4),
                };
                dto.Lon = Math.Round(PhysicsHelper.EcefToGeo((dto.X, dto.Y, dto.Z)).lon, 1);
                list.Add(dto);
            }
            return list;
        }
    }
    public class SatEphCore
    {
        /// 
        /// 卫星编号
        /// 
        public int SatId { get; set; }
        /// 
        /// 时间UTC
        /// 
        public DateTime SatTime { get; set; }
        /// 
        /// 星历发布时刻UTC
        /// 
        public DateTime TleTime { get; set; }
        /// 
        /// 轨道经度
        /// 
        public double Lon { get; set; }
        /// 
        /// 坐标X
        /// 
        public double X { get; set; }
        /// 
        /// 坐标Y
        /// 
        public double Y { get; set; }
        /// 
        /// 坐标Z
        /// 
        public double Z { get; set; }
        /// 
        /// 速度VX(m/s)
        /// 
        public double VX { get; set; }
        /// 
        /// 速度VY(m/s)
        /// 
        public double VY { get; set; }
        /// 
        /// 速度VZ(m/s)
        /// 
        public double VZ { get; set; }
        public override string ToString()
        {
            return $"{SatId}-{SatTime:yyyyMMddHHmmss}-{X},{Y},{Z},{VX},{VY},{VZ}";
        }
    }
}