using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DW5S.DTO;
using DW5S.Entity;
using DW5S.KxcApi;
using DW5S.Repostory;
using DW5S.WebApi;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
namespace DW5S.App.Controllers
{
    /// 
    /// 星历推算功能相关接口
    /// 
    public class XlController : BaseController
    {
        [Autowired]
        private readonly ILogger logger;
        [Autowired]
        private readonly UnitOfWork unitOfWork;
        /// 
        /// 导入Tle星历文件
        /// 
        /// 星历导入参数
        /// 
        [HttpPost]
        public async Task> ImportTleAsync(XlImportDto dto)
        {
            //https://www.space-track.org/documentation#tle网站上有星历文件格式说明
            string line = null;
            try
            {
                var count = await Task.Run(async () =>
                 {
                     var lines = System.IO.File.ReadAllLines(GetLocalFile(dto.File)).ToList();
                     lines.RemoveAll(p => string.IsNullOrWhiteSpace(p));
                     List tmp = new List();
                     for (int i = 0; i < lines.Count; i += 3)
                     {
                         line = lines[i];
                         var satName = lines[i].Trim();
                         if (satName.StartsWith("0 "))
                             satName = satName.Substring(2).Trim();
                         if (satName.StartsWith("TBA"))//待发布的卫星
                             continue;
                         var line1 = lines[i + 1];
                         var line2 = lines[i + 2];
                         if (line1.Length != 69 || line2.Length != 69)
                         {
                             throw new Exception("星历文件内容错误格式");
                         }
                         XlInfo xl = new XlInfo()
                         {
                             SatName = satName,
                             Line1 = line1,
                             Line2 = line2,
                             SatCode = Convert.ToInt32(line1.Substring(2, 5))
                         };
                         var timeStr = line1.Substring(18, 14).Replace(" ", "");//https://www.space-track.org/documentation#tle星历接口中说这里面可以接受空格
                         var yearStr = timeStr.Substring(0, 2);
                         var dayStr = timeStr.Substring(2, timeStr.Length - 2);
                         var day = Convert.ToDouble(dayStr);
                         var year = 2000 + Convert.ToInt32(yearStr);
                         DateTime dt = new DateTime(year, 1, 1, 0, 0, 0);
                         dt = dt.AddDays(day - 1);
                         xl.TimeUTC = dt;
                         tmp.Add(xl);
                     }
                     var repsXl = unitOfWork.Reps();
                    await repsXl.AddRangeAsync(tmp);
                    
                     return tmp.Count;
                 });
                logger.LogInformation($"星历导入成功,共{count}条");
                return Success(new RecordRes(count));
            }
            catch (Exception ex)
            {
                string msg = $"{line}星历导入异常,不支持的格式";
                logger.LogError(ex,msg);
                return Error(msg);
            }
        }
        /// 
        /// 推算某个时间点XYZ星历
        /// 
        /// 推算参数
        /// 
        [HttpPost]
        public AjaxResult Calc(XlCalcDto dto)
        {
            try
            {
                var p = EphHelper.Calc(dto.tleStr, dto.SigTime.ToUtc());
                return Success(new SatEphResDto()
                {
                    SatId = p.SatId,
                    SatTime = p.SatTime.ToLocal(),
                    TleTime = p.TleTime.ToLocal(),
                    Lon = p.Lon,
                    X = p.X,
                    Y = p.Y,
                    Z = p.Z,
                    VX = p.VX,
                    VY = p.VY,
                    VZ = p.VZ,
                });
            }
            catch (Exception ex)
            {
                return Error(ex.Message);
            }
        }
        /// 
        /// 推算某个时间段XYZ星星历
        /// 
        /// 推算参数
        /// 
        [HttpPost]
        public AjaxResult> CalcMult(XlCalcMultDto dto)
        {
            try
            {
                var eph = EphHelper.CalcMult(dto.tleStr, dto.startTime.ToUtc(), dto.endTime.ToUtc(), dto.spanSeconds);
                return Success(eph.Select(p => new EphResDto()
                {
                    SatId = p.SatId,
                    SatTime = p.SatTime.ToLocal(),
                    TleTime = p.TleTime.ToLocal(),
                    Lon = p.Lon,
                    X = p.X,
                    Y = p.Y,
                    Z = p.Z,
                    VX = p.VX,
                    VY = p.VY,
                    VZ = p.VZ,
                }).ToList());
            }
            catch (Exception ex)
            {
                return Error>(ex.Message);
            }
        }
        /// 
        /// 推算卫星某个时间点XYZ星历
        /// 
        /// 推算参数
        /// 
        [HttpPost]
        public async Task> XLCalcAsync(SatDto dto)
        {
            try
            {
                var repsXl = unitOfWork.Reps() as XlRepository;
                var xl1 = await repsXl.GetLatestAsync(dto.SatCode, dto.SigTime);
                if (xl1 == null)
                {
                    string msg = $"系统缺少编号{dto.SatCode}卫星的星历!";
                    logger.LogError(msg);
                    return Error(msg);
                }
                var p = await Task.Run(() =>
                {
                    return EphHelper.Calc(xl1.TwoLine, dto.SigTime.ToUtc());
                });
                return Success(new SatEphResDto()
                {
                    SatId = p.SatId,
                    SatTime = p.SatTime.ToLocal(),
                    TleTime = p.TleTime.ToLocal(),
                    Lon = p.Lon,
                    X = p.X,
                    Y = p.Y,
                    Z = p.Z,
                    VX = p.VX,
                    VY = p.VY,
                    VZ = p.VZ,
                }); ;
            }
            catch (Exception ex)
            {
                return Error(ex.Message);
            }
        }
    }
}