using Microsoft.Win32;
using NEIntelligentControl2.Models;
using NEIntelligentControl2.Models.BoostStation;
using NEIntelligentControl2.Models.Datas;
using NEIntelligentControl2.Models.Messages;
using NEIntelligentControl2.Service.User;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace NEIntelligentControl2.Pages.BoostStation
{
    /// <summary>
    /// 升压站页面
    /// </summary>
    public partial class PageStation : Page
    {
        public static readonly DependencyProperty AngleProperty = DependencyProperty.Register("Angle", typeof(int), typeof(PageStation));
        public static readonly DependencyProperty DataTagProperty = DependencyProperty.Register("DataTag", typeof(string), typeof(PageStation));
        public static readonly DependencyProperty CoordinateProperty = DependencyProperty.Register("Coordinate", typeof(Point), typeof(PageStation));
        public static readonly DependencyProperty IsEditModelProperty = DependencyProperty.Register("IsEditModel", typeof(bool), typeof(PageStation));
        public static readonly DependencyProperty IsNegateProperty = DependencyProperty.Register("IsNegate", typeof(bool), typeof(PageStation));
        /// <summary>
        /// 控件方向
        /// </summary>
        public int Angle { get => (int)GetValue(AngleProperty); set => SetValue(AngleProperty, value); }
        /// <summary>
        /// 数据标签
        /// </summary>
        public string DataTag { get => GetValue(DataTagProperty) as string; set => SetValue(DataTagProperty, value); }
        /// <summary>
        /// 控件坐标
        /// </summary>
        public Point Coordinate { get => (Point)GetValue(CoordinateProperty); set => SetValue(CoordinateProperty, value); }
        /// <summary>
        /// 是否取反
        /// </summary>
        public bool IsNegate { get => (bool)GetValue(IsNegateProperty); set => SetValue(IsNegateProperty, value); }
        private Control _CurrentControl;
        private Control _TempleteControl;
        private bool _IsSelectAction;
        public BoostStationInfo StationInfo { get; set; }
        /// <summary>
        /// 保存动作
        /// </summary>
        public Action<BoostStationInfo> SaveAction { get; set; }
        /// <summary>
        /// 是否被编辑
        /// </summary>
        private bool IsEdited;
        /// <summary>
        /// 是否继续刷新数据
        /// </summary>
        private bool _IsRefreshData;
        /// <summary>
        /// 所有数据点
        /// </summary>
        private List<IBoostStationPoint> _BoostStationPoints;
        /// <summary>
        /// 数据地址
        /// </summary>
        private string _Url = "";
        /// <summary>
        /// 是否是编辑模式
        /// </summary>
        public bool IsEditModel { get => (bool)GetValue(IsEditModelProperty); set => SetValue(IsEditModelProperty, value); }
        /// <summary>
        /// 服务地址
        /// </summary>
        private string _InfoUrl = "";
        /// <summary>
        /// 单击时间
        /// </summary>
        private DateTime _ClickTime;
        private string _BackgroundOld;
        private static readonly object locker = new object();
        private UserManager _UserManager;
        private WEBHelper _WEBHelper;
        public PageStation(UserManager um, WEBHelper web)
        {
            InitializeComponent();
            _UserManager = um;
            _WEBHelper = web;

            try
            {
#if (DEBUG)
                _InfoUrl = ConfigurationManager.AppSettings["ServicePathDebug"];
#else
                _InfoUrl = ConfigurationManager.AppSettings["ServicePath"];
#endif
            }
            catch (Exception ex)
            {
                Console.WriteLine("读取配置文件[ServicePath]出错！", ex);
            }
        }


        private void Init()
        {
            _BoostStationPoints = new List<IBoostStationPoint>();
            try
            {
                if (!string.IsNullOrWhiteSpace(StationInfo.Background))
                {
                    BitmapImage image = GetBackgroundImage(StationInfo.Background);
                    _Canvas.Background = new ImageBrush(image) { Stretch = Stretch.Uniform };
                }
            }
            catch { }
            _Canvas.Children.Clear();
            foreach (var v in StationInfo.BoostStationPointInfos)
            {
                try
                {
                    var obj = Activator.CreateInstance(Type.GetType($"NEIntelligentControl2.Views.BoostStation.{v.Type}")) as IBoostStationPoint;
                    if (obj == null)
                    {
                        continue;
                    }
                    _BoostStationPoints.Add(obj);
                    obj.DataTag = v.DataTag;
                    obj.Proportion = v.Proportion;
                    obj.Info = v.Info;
                    obj.IsNegate = v.IsNegate;
                    var ct = obj as Control;
                    Canvas.SetLeft(ct, v.Coordinate.X);
                    Canvas.SetTop(ct, v.Coordinate.Y);
                    ct.RenderTransform = GetTransform(v);
                    _Canvas.Children.Add(ct);
                }
                catch { }
            }
            var keys = string.Join(",", _BoostStationPoints.Where(b => !string.IsNullOrWhiteSpace(b.DataTag)).Select(b => b.DataTag).ToArray());
            try
            {
#if (DEBUG)
                var ul = ConfigurationManager.AppSettings["DataServicePathDebug"];
#else
                var ul = ConfigurationManager.AppSettings["DataServicePath"];
#endif
                _Url = $"{ul}/ts/latest?keys={keys}";
            }
            catch (Exception ex)
            {
                Console.WriteLine("读取配置文件[DataServicePath]出错！", ex);
            }
        }

        private void Canvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            _CurrentControl?.ReleaseMouseCapture();
            if (e.OriginalSource != sender) return;
            ClosePopup();
        }

        private void ClosePopup(bool isSelect = false)
        {
            if (!isSelect)
            {
                AllNotSelect();
            }
            if (!_Popup.IsOpen)
            {
                return;
            }
            _Popup.IsOpen = false;
            var sp = _CurrentControl as IBoostStationPoint;
            if (sp == null) return;
            sp.DataTag = this.DataTag;
            sp.IsNegate = this.IsNegate;
            Canvas.SetLeft(_CurrentControl, Coordinate.X);
            Canvas.SetTop(_CurrentControl, Coordinate.Y);

            _CurrentControl = null;

            IsEdited = true;
        }

        private void AllNotSelect()
        {
            var vvs = GetSelectedItems();
            foreach (var v in vvs)
            {
                var issp = v as IBoostStationPoint;
                if (issp != null)
                {
                    issp.IsSelected = false;
                }
            }
        }

        private Transform GetTransform()
        {
            RotateTransform rt = new RotateTransform();
            if (_TempleteControl != null)
            {
                RotateTransform ort = _TempleteControl.RenderTransform as RotateTransform;
                rt.Angle = ort.Angle;
                rt.CenterX = ort.CenterX;
                rt.CenterY = ort.CenterY;
            }
            return rt;
        }

        private Transform GetTransform(Control obj)
        {
            RotateTransform rt = new RotateTransform();
            rt.Angle = this.Angle;
            rt.CenterX = obj.ActualWidth / 2;
            rt.CenterY = obj.ActualHeight / 2;
            return rt;
        }

        private Transform GetTransform(BoostStationPointInfo v)
        {
            RotateTransform rt = new RotateTransform();
            rt.Angle = v.Angle;
            rt.CenterX = v.CenterCoordinate.X;
            rt.CenterY = v.CenterCoordinate.Y;
            return rt;
        }

        /// <summary>
        /// 小控件被单击
        /// </summary>
        private void PointClicked(Control c)
        {
            if ((c as IBoostStationPoint).IsTemplete)
            {
                TempleteClicked();
            }
            else
            {
                SelectClicked(c);
            }
        }

        private void SelectClicked(Control c)
        {
            _ClickTime = DateTime.Now;
            if (_Popup.IsOpen)
            {
                ClosePopup(true);
            }
            _CurrentControl = c;
            _CurrentControl.CaptureMouse();
            Coordinate = new Point(Canvas.GetLeft(c), Canvas.GetTop(c));
            DataTag = (c as IBoostStationPoint).DataTag;
            IsNegate = (c as IBoostStationPoint).IsNegate;
            _Popup.IsOpen = true;
            _LBISelect.Focus();
        }

        private void TempleteClicked()
        {
            var obj = Activator.CreateInstance(_TempleteControl.GetType()) as Control;
            if (obj == null) return;
            (obj as IBoostStationPoint).Clicked = PointClicked;
            (obj as IBoostStationPoint).IsEditModel = true;
            (obj as IBoostStationPoint).Proportion = (_TempleteControl as IBoostStationPoint).Proportion;
            Canvas.SetLeft(obj, Canvas.GetLeft(_TempleteControl));
            Canvas.SetTop(obj, Canvas.GetTop(_TempleteControl));
            obj.RenderTransform = GetTransform();
            _Canvas.Children.Add(obj);

            IsEdited = true;
        }

        private void Canvas_MouseMove(object sender, MouseEventArgs e)
        {
            if (_IsSelectAction)
            {
                if (e.LeftButton != MouseButtonState.Pressed || e.OriginalSource == _Canvas || (DateTime.Now - _ClickTime).TotalMilliseconds < 300) return;
                MovePoint(_CurrentControl, e);
                _Popup.IsOpen = false;
            }
            else if (_TempleteControl != null)
            {
                MovePoint(_TempleteControl, e);
            }
        }


        private void _Canvas_MouseLeave(object sender, MouseEventArgs e)
        {
            if (_TempleteControl == null) return;
            _TempleteControl.Visibility = Visibility.Collapsed;
            if (_Popup.IsOpen)
            {
                _Popup.IsOpen = false;
            }
        }

        private void _Canvas_MouseEnter(object sender, MouseEventArgs e)
        {
            if (_TempleteControl == null) return;
            _TempleteControl.Visibility = Visibility.Visible;
        }

        private void ListBoxItem_Selected(object sender, RoutedEventArgs e)
        {
            string action = ((Control)sender).Tag as string;

            _IsSelectAction = action == "Select";
            if (_TempleteControl != null)
            {
                _Canvas.Children.Remove(_TempleteControl);
            }
            if (_IsSelectAction)
            {
                _CurrentControl = null;
                _TempleteControl?.ReleaseMouseCapture();
                _TempleteControl = null;
            }
            else
            {
                _TempleteControl?.CaptureMouse();
            }
            var ct = Type.GetType($"NEIntelligentControl2.Views.BoostStation.{action}");
            if (ct == null) return;
            var obj = Activator.CreateInstance(ct);
            if (!(obj is IBoostStationPoint)) return;
            (obj as IBoostStationPoint).IsTemplete = true;
            (obj as IBoostStationPoint).IsEditModel = true;
            (obj as IBoostStationPoint).Clicked = PointClicked;
            _TempleteControl = obj as Control;
            _TempleteControl.Loaded += PointLoaded;
            _Canvas.Children.Add(obj as Control);
        }

        private void PointLoaded(object sender, RoutedEventArgs e)
        {
            Control c = sender as Control;
            if (c == null) return;
            c.RenderTransform = GetTransform(c);
        }

        private void MovePoint(FrameworkElement c, MouseEventArgs e)
        {
            if (c == null) return;
            Point p = e.GetPosition(_Canvas);
            Canvas.SetTop(c, p.Y - c.ActualHeight / 2);
            Canvas.SetLeft(c, p.X - c.ActualWidth / 2);
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            switch (((Control)sender).Tag)
            {
                case "angle":// 角度
                    AngleChange();
                    break;
                case "background":// 选择背景图片
                    ChoseBackground();
                    break;
                case "delete":// 删除
                    DeletePoint();
                    break;
                case "save":// 保存
                    Save();
                    break;
                case "close":// 放弃保存
                    Close();
                    break;
                case "narrow":// 缩小控件
                    Narrow();
                    break;
                case "enlarge":// 放大控件
                    Enlarge();
                    break;
                default: return;
            }
        }

        /// <summary>
        /// 放大控件
        /// </summary>
        private void Enlarge()
        {
            if (_CurrentControl != null)
            {
                (_CurrentControl as IBoostStationPoint).Zoom(1);
            }
            if (_TempleteControl != null)
            {
                (_TempleteControl as IBoostStationPoint).Zoom(1);
            }
        }

        /// <summary>
        /// 缩小控件
        /// </summary>
        private void Narrow()
        {
            if (_CurrentControl != null)
            {
                (_CurrentControl as IBoostStationPoint).Zoom(-1);
            }
            if (_TempleteControl != null)
            {
                (_TempleteControl as IBoostStationPoint).Zoom(-1);
            }
        }

        private void Close()
        {
            var v = MessageBox.Show("放弃保存？", "提示", MessageBoxButton.YesNo);
            if (v != MessageBoxResult.Yes) return;
            if (StationInfo.Background != _BackgroundOld)
            {
                StationInfo.Background = _BackgroundOld;
                BitmapImage image = GetBackgroundImage(StationInfo.Background);
                _Canvas.Background = new ImageBrush(image) { Stretch = Stretch.Uniform };
            }
            ToNormalModel();
        }

        /// <summary>
        /// 回到正常模式
        /// </summary>
        private void ToNormalModel()
        {
            _ToolPane.Visibility = Visibility.Collapsed;
            IsEdited = false;
            IsEditModel = false;
            _Popup.IsOpen = false;
            lock (locker)
            {
                Init();
            }
        }

        /// <summary>
        /// 保存
        /// </summary>
        private void Save()
        {
            try
            {
                if (!IsEdited)
                {
                    ToNormalModel();
                    return;
                }
                if (_TempleteControl == null)
                {
                    _Canvas.Children.Remove(_TempleteControl);
                    _TempleteControl = null;
                }
                StationInfo.BoostStationPointInfos = GetBoostStationPointInfo();
                StationInfo.UpdatedDate = DateTime.Now.Ticks;
                SaveAction?.Invoke(StationInfo);

                ToNormalModel();
            }
            catch (Exception e) { Console.WriteLine(e.ToString()); }
        }

        /// <summary>
        /// 获取所有控件信息
        /// </summary>
        /// <returns></returns>
        private List<BoostStationPointInfo> GetBoostStationPointInfo()
        {
            List<BoostStationPointInfo> bspis = new List<BoostStationPointInfo>();
            foreach (var v in _Canvas.Children)
            {
                if (!(v is IBoostStationPoint))
                {
                    continue;
                }
                var point = v as IBoostStationPoint;
                var ct = v as Control;
                BoostStationPointInfo bspi = new BoostStationPointInfo();
                bspi.Type = v.GetType().Name;
                bspi.DataTag = point.DataTag;
                bspi.Proportion = point.Proportion;
                bspi.Info = point.Info;
                bspi.IsNegate = point.IsNegate;
                RotateTransform rotate = ct.RenderTransform as RotateTransform;
                if (rotate != null)
                {
                    bspi.CenterCoordinate = new Point(rotate.CenterX, rotate.CenterY);
                    bspi.Angle = (int)rotate.Angle;
                }
                Point pt = new Point(Canvas.GetLeft(ct), Canvas.GetTop(ct));
                bspi.Coordinate = pt;
                bspis.Add(bspi);
            }
            return bspis;
        }

        /// <summary>
        /// 更改角度
        /// </summary>
        private void AngleChange()
        {
            Angle = Angle >= 270 ? 0 : Angle + 90;
            if (_CurrentControl != null)
            {
                _CurrentControl.RenderTransform = GetTransform(_CurrentControl);
            }
            if (_TempleteControl != null)
            {
                var tr = _TempleteControl.RenderTransform as RotateTransform;
                tr.Angle = this.Angle;
                _TempleteControl.RenderTransform = tr;
            }
            var vs = GetSelectedItems();
            foreach (var v in vs)
            {
                v.RenderTransform = GetTransform(v);
            }
            IsEdited = true;
        }

        /// <summary>
        /// 删除标签点
        /// </summary>
        private void DeletePoint()
        {
            List<Control> list = GetSelectedItems();
            if (list.Count <= 0) return;
            foreach (var v in list)
            {
                _Canvas.Children.Remove(v);
            }
            IsEdited = true;
        }

        private List<Control> GetSelectedItems()
        {
            List<Control> ls = new List<Control>();
            foreach (var v in _Canvas.Children)
            {
                var c = v as IBoostStationPoint;
                if (c == null || !c.IsSelected) continue;
                ls.Add(c as Control);
            }
            return ls;
        }

        private void ChoseBackground()
        {
            var dl = new OpenFileDialog();
            dl.Filter = "图片(.png)|*.png";
            dl.Title = "选择背景图片";
            var b = dl.ShowDialog();
            if (b == null || b == false) return;
            try
            {
                _BackgroundOld = StationInfo.Background;
                StationInfo.Background = GetBackgroundByFile(dl.FileName);
                BitmapImage image = GetBackgroundImage(StationInfo.Background);
                _Canvas.Background = new ImageBrush(image) { Stretch = Stretch.Uniform };
                IsEdited = true;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        /// <summary>
        /// 从文件中获取背景图片文字
        /// </summary>
        /// <exception cref="NotImplementedException"></exception>
        private string GetBackgroundByFile(string url)
        {
            var bs = File.ReadAllBytes(url);
            return Convert.ToBase64String(bs);
        }

        private BitmapImage GetBackgroundImage(string v)
        {
            if (string.IsNullOrWhiteSpace(v)) return null;
            BitmapImage bt = new BitmapImage();
            bt.BeginInit();
            bt.CacheOption = BitmapCacheOption.OnLoad;
            var bs = Convert.FromBase64String(v);
            using (Stream stream = new MemoryStream(bs))
            {
                bt.StreamSource = stream;
                bt.EndInit();
                bt.Freeze();
            }
            return bt;
        }

        private void MenuItem_Click(object sender, RoutedEventArgs e)
        {
            switch (((Control)sender).Tag)
            {
                case "edit":// 编辑
                    EditModel();
                    break;
            }
        }

        /// <summary>
        /// 开启编辑模式
        /// </summary>
        private void EditModel()
        {
            if (!_UserManager.IsLogined || _UserManager.User.Level != Models.User.UserLevel.Administrator)
            {
                MessageBox.Show("请登录管理员账号进入编辑模式！", "提示：", MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }
            _BackgroundOld = StationInfo.Background;
            IsEditModel = true;
            _ToolPane.Visibility = Visibility.Visible;
            foreach (var v in _Canvas.Children)
            {
                var bsp = v as IBoostStationPoint;
                if (bsp == null) continue;
                bsp.Clicked = PointClicked;
                bsp.IsEditModel = true;
            }
        }

        private void Page_Loaded(object sender, RoutedEventArgs e)
        {
            Init();
            this._IsRefreshData = true;
            Task.Factory.StartNew(RefreshData, TaskCreationOptions.LongRunning);
            Task.Factory.StartNew(CheckUpdate, TaskCreationOptions.LongRunning);
        }

        /// <summary>
        /// 检查更新
        /// </summary>
        private async void CheckUpdate()
        {
            while (_IsRefreshData)
            {
                try
                {
                    var dtstr = _WEBHelper.HttpGetString($"{_InfoUrl}/api/station/boost_station/update_time/{StationInfo.Id}");
                    long.TryParse(dtstr, out long dt);
                    if (dt > 0 && dt != StationInfo.UpdatedDate)
                    {
                        var info = _WEBHelper.HttpGetJSON<BoostStationInfo>($"{_InfoUrl}/api/station/boost_station/{StationInfo.Id}");
                        Dispatcher.Invoke(() =>
                        {
                            lock (locker)
                            {
                                StationInfo = info;
                                Init();
                            }
                        });
                    }
                }
                catch { }
                await Task.Delay(10000);
            }
        }

        private async void RefreshData()
        {
            while (_IsRefreshData)
            {
                try
                {
                    var vs = _WEBHelper.HttpGetJSON<Dictionary<string, TsData>>(_Url);
                    if (vs != null && vs.Count > 0)
                    {
                        Dispatcher?.Invoke(() =>
                        {
                            lock (locker)
                            {
                                foreach (var v in _BoostStationPoints)
                                {
                                    if (string.IsNullOrWhiteSpace(v.DataTag))
                                    {
                                        continue;
                                    }
                                    if (vs.ContainsKey(v.DataTag))
                                    {
                                        v.Value = vs[v.DataTag].Value;
                                    }
                                }
                            }
                        });
                    }
                    Console.WriteLine($"刷新：{StationInfo.Id}");
                }
                catch { }

                await Task.Delay(2000);
            }
        }

        private void Page_Unloaded(object sender, RoutedEventArgs e)
        {
            this._IsRefreshData = false;
            if (IsEdited)
            {
                var v = MessageBox.Show("有未保存的改动，是否保存？", "提示：", MessageBoxButton.YesNo);
                if (v == MessageBoxResult.Yes)
                {
                    Save();
                }
            }
            if (IsEditModel)
            {
                ToNormalModel();
            }
        }

        private void _Canvas_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (_Popup.IsOpen)
            {
                ClosePopup();
            }
            _LBTools.SelectedIndex = 0;
        }

        private void Direction_Click(object sender, RoutedEventArgs e)
        {
            if (_CurrentControl == null) return;
            int dtop = 0;
            int dleft = 0;
            switch (((Control)sender).Tag)
            {
                case "left":
                    dleft = -1;
                    break;
                case "right":
                    dleft = 1;
                    break;
                case "up":
                    dtop = -1;
                    break;
                case "down":
                    dtop = 1;
                    break;
                default: return;
            }
            double top = Canvas.GetTop(_CurrentControl) + dtop;
            double left = Canvas.GetLeft(_CurrentControl) + dleft;
            Coordinate = new Point(left, top);
            Canvas.SetTop(_CurrentControl, top);
            Canvas.SetLeft(_CurrentControl, left);
        }
    }
}
