using FlyADBase;
using GalaSoft.MvvmLight.Command;
using Newtonsoft.Json;

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Threading;

namespace Flyad7_WPF
{
    [JsonObject(MemberSerialization.OptIn)]
    public class AutoGetGridAdv:INotifyPropertyChanged
    {
        IFlyADClientAdv flyad;

        public bool IsError { get; set; }

        public string ErrMsg { get; set; }

        public string ProgressMsg { get; set; }
        
        public bool IsRunning { get; private set; }

        [JsonProperty]
        public int FB_Pos1 { get; set; } = 1000;

        [JsonProperty]
        public int FB_Pos2 { get; set; } = 3000;

        [JsonProperty]
        public int StartV { get; set; } = 100;

        [JsonProperty]
        public int StepV { get; set; } = 100;

        [JsonProperty]
        public int EndV { get; set; } = 2000;

        public RelayCommand StartCmd { get; private set; }
        public RelayCommand StopCmd { get; private set; }
        public RelayCommand AnalyzeCmd { get; private set; }
        List<TimeGridAdv2EventArgs> timeGridAdv2Datas = new List<TimeGridAdv2EventArgs>();
        public AutoGetGridAdv(IFlyADClientAdv flyad)
        {
            this.flyad = flyad;
            StartCmd = new RelayCommand(Start);
            StopCmd = new RelayCommand(Stop);
            AnalyzeCmd = new RelayCommand(Analyze);
            Load();

            this.PropertyChanged += AutoSave;
            
        }




        CancellationTokenSource cancellationTokenSource;
        async void Start() 
        {
            
            if (IsRunning)
                return;

            

            cancellationTokenSource = new CancellationTokenSource();
            IsError = false;
            IsRunning = true;
            ProgressMsg = "准备动作，到达 开始位置";
            await Task.Delay(1);
            flyad.SetVelocity((UInt32)(StartV + EndV) / 2);
            flyad.Runto(FB_Pos1);
            if (!await Wait()) goto _end;

            ProgressMsg = "正式开始";
            await Task.Delay(1);
            //正式开始
            timeGridAdv2Datas.Clear();
            flyad.TimeGridAdv2Event += Flyad_TimeGridAdv2Event;
            int v = StartV;
            int cnt = (EndV - StartV) / StepV;
            for(int j=0;j<cnt;j++)
            {
                
                flyad.SetVelocity((UInt32)v);
                for (int i = 0; i < 2; i++)
                {
                    ProgressMsg = $"{j*2+i}/{cnt*2} 以速度 {v}pps 来回扫描";
                    await Task.Delay(1);
                    flyad.Runto(FB_Pos2);
                    if (!await Wait()) goto _end;
                    flyad.Runto(FB_Pos1);
                    if (!await Wait()) goto _end;
                }
                v += StepV;
            }
        _end:
            await Task.Delay(1000);//等1秒，等最后一个TimeGridAdvEvent收到
            flyad.TimeGridAdv2Event -= Flyad_TimeGridAdv2Event;
            
            //保存数据
            string strDesktopPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
            string path = System.IO.Path.Combine(strDesktopPath, $"autoGridAdv_{DateTime.Now.ToString("yyyyMMdd_HHmmss")}.json");
            string json = Newtonsoft.Json.JsonConvert.SerializeObject(timeGridAdv2Datas);
            File.WriteAllText(path, json);

            ProgressMsg = $"成功保存到 {path}";
            timeGridAdv2Datas.Clear();
            IsRunning = false;
        }

        private void Flyad_TimeGridAdv2Event(object sender, TimeGridAdv2EventArgs e)
        {
            timeGridAdv2Datas.Add(e);
        }
        async Task<bool> Wait() 
        {
            while (true)
            {
                try
                {
                    await Task.Delay(2000, cancellationTokenSource.Token);
                }
                catch 
                {
                    //被叫醒了
                    ErrMsg = "强制退出";
                    IsError = true;
                    await Task.Delay(1);
                    return false;
                }
                if (!flyad.IsConnected)
                {
                    ErrMsg = "连接断开";
                    IsError = true;
                    await Task.Delay(1);
                    return false;
                }
                if (flyad.DriveStatus == DRIVE_MAN_STATUS.RUNNING)
                {
                    continue;
                }
                else if (flyad.DriveStatus == DRIVE_MAN_STATUS.STOP)
                {
                    return true;
                }
                else 
                {
                    ErrMsg = $"异常停止 flyad.DriveStatus={flyad.DriveStatus}";
                    IsError = true;
                    return false;
                }
            }
        }
        void Stop() 
        {
            if (!IsRunning)
                return;
            if (cancellationTokenSource == null)
                return;
            if (cancellationTokenSource.IsCancellationRequested)
                return;

            cancellationTokenSource.Cancel();
        }

        private void Analyze()
        {
            WdGridAdvAnalyze wd = new WdGridAdvAnalyze();
            wd.Init();
            wd.ShowDialog();
        }
        public event PropertyChangedEventHandler PropertyChanged;

        private bool isIgnoreSave;
        private async void AutoSave(object sender, PropertyChangedEventArgs e)
        {
            if (isIgnoreSave)
                return;

            if (this.GetType()
                .GetProperty(e.PropertyName)
                .GetCustomAttributes(typeof(JsonPropertyAttribute), false)
                .Count() > 0)
            {
                isIgnoreSave = true;
                await Task.Delay(5000);//Task.Yield();
                Save();
                isIgnoreSave = false;
            }
        }

        void Save() 
        {
            try
            {
                string json = Newtonsoft.Json.JsonConvert.SerializeObject(this, Formatting.Indented);
                File.WriteAllText("autoGridAdv.json", json);
            }
            catch (Exception e ) 
            {
            
            }
        }
        void Load() 
        {
            try
            {
                string json = File.ReadAllText("autoGridAdv.json");
                isIgnoreSave = true;
                Newtonsoft.Json.JsonConvert.PopulateObject(json, this);
                isIgnoreSave = false;
            }
            catch (Exception e)
            {

            }
        }
    }
}
