using MECF.Framework.Common.CommonData;
using OpenSEMI.ClientBase;
using System.Collections.Generic;
using System.Globalization;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using MECF.Framework.Common.DataCenter;
using MECF.Framework.UI.Core.Converters;
using System.Text;
using System;
using Aitex.Core.RT.Log;
using System.Reflection;
using System.Diagnostics;
using System.Windows.Documents;
using DocumentFormat.OpenXml.Wordprocessing;

namespace MECF.Framework.UI.Client.CenterViews.Dialogs
{
    public class SystemInfoViewModel: DialogViewModel<string>
    {
        #region Variables

        private const string KEY_ASSE = "System.AssembliesInfo";
        private const string KEY_RN = "System.ReleaseNote";

        private readonly CancellationTokenSource _cts;
        private readonly MarkdownToHtmlConverter _mdToHtmlConverter;

        private List<ReferencedAssemblyInfo> _dependencyAssembliesInfo;
        private string _mdReleaseNote;
        private Task _taskLoadData;
        
        #endregion

        #region Constructors

        public SystemInfoViewModel()
        {
            _cts = new CancellationTokenSource();
            _mdToHtmlConverter = new MarkdownToHtmlConverter();

            PollDataAsync();
        }

        #endregion

        #region Properties

        public string SicUIVersion => $"SicUI Version {Assembly.GetEntryAssembly().GetName().Version}";


        public List<ReferencedAssemblyInfo> DependenciesInfo
        {
            get => _dependencyAssembliesInfo;
            private set
                {
                _dependencyAssembliesInfo = value;
                NotifyOfPropertyChange();
            }
        }

        public string MdReleaseNote
        {
            get => _mdReleaseNote;
            private set
            {
                _mdReleaseNote = value;
                NotifyOfPropertyChange();
            }
        }

        #endregion

        #region Methods

        protected override void OnDeactivate(bool close)
        {
            _cts?.Cancel();
            _taskLoadData?.Dispose();
        }

        private void PollData()
        {
            var dict = QueryDataClient.Instance.Service.PollData(new[] { KEY_ASSE, KEY_RN });
            var list = dict[KEY_ASSE] as List<ReferencedAssemblyInfo>;
            var releaseNote = _mdToHtmlConverter.Convert(dict[KEY_RN], null, null, CultureInfo.CurrentCulture)?.ToString();
            DependenciesInfo = list;
            MdReleaseNote = releaseNote;
        }

        private void PollDataAsync()
        {
            // Load信息用于提醒用户正在加载
            DependenciesInfo = new List<ReferencedAssemblyInfo>(new[]
            {
                 new ReferencedAssemblyInfo()
                 {
                     Name = "Loading..."
                 }
             });
            
            // 异步拉取数据，以便窗口及时弹出
            List<ReferencedAssemblyInfo> list = null;
            var releaseNote = "";
            _taskLoadData = Task.Run(() =>
            {
                var dict = QueryDataClient.Instance.Service.PollData(new[] { KEY_ASSE, KEY_RN });
                list = dict[KEY_ASSE] as List<ReferencedAssemblyInfo>;
                releaseNote = _mdToHtmlConverter.Convert(dict[KEY_RN], null, null, CultureInfo.CurrentCulture)?.ToString();
            }, _cts.Token).ContinueWith(t =>
            {
                if (t.IsCompleted)
                {
                    Application.Current?.Dispatcher.Invoke(() =>
                    {
                        DependenciesInfo = list;
                        MdReleaseNote = releaseNote;
                        Debug.WriteLine($"{MdReleaseNote.Substring(0, 100)} =- {releaseNote.Substring(0, 100)}");
                    });
                }
            }, _cts.Token);
        }

        public void CopyAssembliesInfo()
        {
            if(DependenciesInfo.Count > 0)
            {
                var sb = new StringBuilder();
                foreach(var dependency in DependenciesInfo)
                {
                    sb.AppendLine(dependency.ToString());
                }

                try
                {
                    Clipboard.SetText(sb.ToString());
                }
                catch (Exception ex)
                {
                    LOG.Error($"Unable to copy assemblis info to clipboard, {ex.Message}");
                }
            }
        }

        #endregion
    }
}
