using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using AIStudio.Wpf.DiagramDesigner;
using AIStudio.Wpf.DiagramDesigner.Geometrys;
using AIStudio.Wpf.DiagramDesigner.Serializable;
using AIStudio.Wpf.Flowchart.Models;

namespace AIStudio.Wpf.Flowchart.Controls
{
    /// <summary>
    /// FlowchartEditor.xaml 的交互逻辑
    /// </summary>
    [TemplatePart(Name = PART_DiagramControl, Type = typeof(DiagramControl))]
    public partial class FlowchartEditor : Control
    {
        public const string PART_DiagramControl = "PART_DiagramControl";
        private DiagramControl _diagramControl;

        private IDiagramViewModel _diagramViewModel;

        static FlowchartEditor()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(FlowchartEditor), new FrameworkPropertyMetadata(typeof(FlowchartEditor)));
        }

        public FlowchartEditor()
        {
            _diagramViewModel = new DiagramViewModel();
            _diagramViewModel.DiagramOption.LayoutOption.ShowGrid = true;
            _diagramViewModel.DiagramOption.LayoutOption.GridCellSize = new SizeBase(125 / ScreenHelper.ScreenScale, 125 / ScreenHelper.ScreenScale);
            _diagramViewModel.DiagramOption.LayoutOption.GridMarginSize = new Size(0, 0);
            _diagramViewModel.DiagramOption.LayoutOption.CellHorizontalAlignment = CellHorizontalAlignment.Center;
            _diagramViewModel.DiagramOption.LayoutOption.CellVerticalAlignment = CellVerticalAlignment.Center;
            _diagramViewModel.DiagramOption.LayoutOption.PageSizeType = PageSizeType.Custom;
            _diagramViewModel.DiagramOption.LayoutOption.PageSize = new SizeBase(double.NaN, double.NaN);
            _diagramViewModel.ColorViewModel = new ColorViewModel() { LineWidth = 2 };
            _diagramViewModel.DrawModeViewModel = new DrawModeViewModel() { LineDrawMode = DrawMode.ConnectingLineSmooth };

            _diagramViewModel.PropertyChanged += DiagramViewModel_PropertyChanged;
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            _diagramControl = GetTemplateChild(PART_DiagramControl) as DiagramControl;
            _diagramControl.HorizontalAlignment = HorizontalAlignment.Stretch;
            _diagramControl.VerticalAlignment = VerticalAlignment.Stretch;
            _diagramControl.DataContext = _diagramViewModel;

            GetDataFunc = GetData;
        }

        private void DiagramViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "IsSelected")
            {
                SelectedObject = _diagramViewModel.SelectedItem;
            }
        }

        //一点要绑定不为空的FlowchartModel才能用，即便为空的也要new一个再来绑定
        public static readonly DependencyProperty DataProperty =
          DependencyProperty.Register(nameof(Data),
                                     typeof(string),
                                     typeof(FlowchartEditor),
                                     new FrameworkPropertyMetadata(null, OnDataChanged));

        public string Data
        {
            get
            {
                return (string)GetValue(DataProperty);
            }
            set
            {
                SetValue(DataProperty, value);
            }
        }
        private static void OnDataChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var view = d as FlowchartEditor;
            var json = e.NewValue as string;
            if (json != null)
            {
                view.CreateFlowchartModel(json);
            }
        }

        private void CreateFlowchartModel(string json)
        {
            _diagramViewModel.IsLoading = true;
            _diagramViewModel.Items.Clear();
            _diagramViewModel.ToObject(json);
            _diagramViewModel.IsLoading = false;
        }

        public static readonly DependencyProperty GetDataFuncProperty =
        DependencyProperty.Register(nameof(GetDataFunc),
                                   typeof(Func<string>),
                                   typeof(FlowchartEditor),
                                   new FrameworkPropertyMetadata(null));
        public Func<string> GetDataFunc
        {
            get
            {
                return (Func<string>)this.GetValue(GetDataFuncProperty);
            }
            set
            {
                this.SetValue(GetDataFuncProperty, value);
            }
        }

        public Func<string> GetData
        {
            get
            {
                return new Func<string>(() => _diagramViewModel.ToJson());
            }
        }


        public static readonly DependencyProperty ModeProperty =
         DependencyProperty.Register(nameof(Mode),
                                    typeof(string),
                                    typeof(FlowchartEditor),
                                    new FrameworkPropertyMetadata("Edit", OnModeChanged));

        public string Mode
        {
            get
            {
                return (string)GetValue(ModeProperty);
            }
            set
            {
                SetValue(ModeProperty, value);
            }
        }

        private static void OnModeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var view = d as FlowchartEditor;
            var mode = e.NewValue as string;
            if (mode != "Edit")
            {
                view._diagramViewModel.IsReadOnly = true;
            }
            else
            {
                view._diagramViewModel.IsReadOnly = false;
            }
        }

        #region ToolBox
        /// <summary>
        /// 附加组件模板
        /// </summary>
        public static readonly DependencyProperty ToolBoxProperty = DependencyProperty.Register(
            nameof(ToolBox), typeof(ControlTemplate), typeof(FlowchartEditor), new FrameworkPropertyMetadata(default(ControlTemplate)));

        public ControlTemplate ToolBox
        {
            get
            {
                return (ControlTemplate)GetValue(ToolBoxProperty);
            }
            set
            {
                SetValue(ToolBoxProperty, value);
            }
        }
        #endregion

        #region PropertiesBox
        /// <summary>
        /// 附加组件模板
        /// </summary>
        public static readonly DependencyProperty PropertiesBoxProperty = DependencyProperty.Register(
            nameof(PropertiesBox), typeof(ControlTemplate), typeof(FlowchartEditor), new FrameworkPropertyMetadata(default(ControlTemplate)));

        public ControlTemplate PropertiesBox
        {
            get
            {
                return (ControlTemplate)GetValue(PropertiesBoxProperty);
            }
            set
            {
                SetValue(PropertiesBoxProperty, value);
            }
        }
        #endregion

        #region SelectedObject

        public static readonly DependencyProperty SelectedObjectProperty = DependencyProperty.Register(nameof(SelectedObject), typeof(object), typeof(FlowchartEditor), new UIPropertyMetadata(default(object)));
        public object SelectedObject
        {
            get
            {
                return (object)GetValue(SelectedObjectProperty);
            }
            set
            {
                SetValue(SelectedObjectProperty, value);
            }
        }

        #endregion 

        #region Users
        public static readonly DependencyProperty UsersProperty
            = DependencyProperty.Register(nameof(Users), typeof(List<SelectOption>), typeof(FlowchartEditor), new UIPropertyMetadata(default(List<SelectOption>)));
        public List<SelectOption> Users
        {
            get
            {
                return (List<SelectOption>)GetValue(UsersProperty);
            }
            set
            {
                SetValue(UsersProperty, value);
            }
        }
        #endregion

        #region Roles
        public static readonly DependencyProperty RolesProperty
            = DependencyProperty.Register(nameof(Roles), typeof(List<SelectOption>), typeof(FlowchartEditor), new UIPropertyMetadata(default(List<SelectOption>)));
        public List<SelectOption> Roles
        {
            get
            {
                return (List<SelectOption>)GetValue(RolesProperty);
            }
            set
            {
                SetValue(RolesProperty, value);
            }
        }
        #endregion
    }
}
