using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows.Media;
using AIStudio.Wpf.DiagramDesigner;
using AIStudio.Wpf.DiagramDesigner.Models;
using AIStudio.Wpf.DiagramDesigner.Services;
using AIStudio.Wpf.SFC.Models;

namespace AIStudio.Wpf.SFC.ViewModels
{
    public class SFCNode : DesignerItemViewModelBase
    {
        protected IUIVisualizerService visualiserService;

        public SFCNode(SFCNodeKinds kind) : this(null, kind)
        {

        }

        public SFCNode(IDiagramViewModel root, SFCNodeKinds kind) : base(root)
        {
            ColorViewModel.FillColor.Color = Colors.Blue;
            Kind = kind;
            ItemWidth = 80;
            ItemHeight = 40;
        }

        public SFCNode(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
        {

        }

        public SFCNode(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
        {

        }

        public override SelectableItemBase GetSerializableObject()
        {
            return new SFCNodeDesignerItem(this);
        }

        protected override void Init(IDiagramViewModel root, bool initNew)
        {           
            IsInnerConnector = true;
            ShowRotate = false;
            ShowArrow = false;
            ShowText = true;
            IsReadOnlyText = true;

            base.Init(root, initNew);

            visualiserService = ApplicationServicesProvider.Instance.Provider.VisualizerService;
        }

        protected override void InitNew()
        {
            ClearConnectors();
        }

        protected override void LoadDesignerItemViewModel(SelectableItemBase designerbase)
        {
            base.LoadDesignerItemViewModel(designerbase);

            if (designerbase is SFCNodeDesignerItem designer)
            {
                this.Kind = designer.Kind;
                this.Expression = designer.Expression;

                foreach (var connector in designer.Connectors)
                {
                    FullyCreatedConnectorInfo fullyCreatedConnectorInfo = new FullyCreatedConnectorInfo(this.Root, this, connector);
                    if (fullyCreatedConnectorInfo.Orientation == ConnectorOrientation.Left)
                    {
                        Input.Add(Input.Count, fullyCreatedConnectorInfo);
                    }
                    else if (fullyCreatedConnectorInfo.Orientation == ConnectorOrientation.Right)
                    {
                        Output.Add(Output.Count, fullyCreatedConnectorInfo);
                    }
                    AddConnector(fullyCreatedConnectorInfo);
                }

                if (this is SFCActionNode actionNode)
                {
                    actionNode.LinkPoint = designer.LinkPoints.FirstOrDefault();
                }
                else if (this is SFCConditionNode sFCConditionNode)
                {
                    sFCConditionNode.LinkPoint = new System.Collections.ObjectModel.ObservableCollection<LinkPoint>(designer.LinkPoints);
                }
                else if (this is Simulate_SolenoidViewModel simulate_SolenoidViewModel)
                {
                    simulate_SolenoidViewModel.DILinkPoint = designer.LinkPoints.FirstOrDefault();
                    simulate_SolenoidViewModel.DOLinkPoint = designer.LinkPoints.LastOrDefault();
                }
                else if (this is Simulate_StartViewModel simulate_StartViewModel)
                {
                    simulate_StartViewModel.LinkPoint = designer.LinkPoints.FirstOrDefault();
                }
                else if (this is Simulate_TankViewModel simulate_TankViewModel)
                {
                    simulate_TankViewModel.LinkPoint = designer.LinkPoints.FirstOrDefault();
                }
            }
        }

        public Dictionary<int, FullyCreatedConnectorInfo> Input { get; set; } = new Dictionary<int, FullyCreatedConnectorInfo>();
        public Dictionary<int, FullyCreatedConnectorInfo> Output { get; set; } = new Dictionary<int, FullyCreatedConnectorInfo>();
        public Dictionary<int, FullyCreatedConnectorInfo> Action { get; set; } = new Dictionary<int, FullyCreatedConnectorInfo>();

        public virtual void ExecuteAddLeftInput(object parameter)
        {
            FullyCreatedConnectorInfo connector = new FullyCreatedConnectorInfo(this, ConnectorOrientation.Left, true);
            connector.XRatio = 0;
            Input.Add(Input.Count, connector);
            for (int i = 0; i < Input.Values.Count; i++)
            {
                Input[i].YRatio = (i + 1.0) / (Input.Values.Count + 1.0);
            }
            AddConnector(connector);
        }

        public virtual void ExecuteAddTopInput(object parameter)
        {
            FullyCreatedConnectorInfo connector = new FullyCreatedConnectorInfo(this, ConnectorOrientation.Top, true);
            connector.YRatio = 0;
            Input.Add(Input.Count, connector);
            for (int i = 0; i < Input.Values.Count; i++)
            {
                Input[i].XRatio = (i + 1.0) / (Input.Values.Count + 1.0);
                if (Output.ContainsKey(i))
                {
                    Output[i].XRatio = Input[i].XRatio;
                }
            }
            AddConnector(connector);
        }

        public virtual void ExecuteAddRightOutput(object parameter)
        {
            FullyCreatedConnectorInfo connector = new FullyCreatedConnectorInfo(this, ConnectorOrientation.Right, true);
            connector.XRatio = 1;
            Output.Add(Output.Count, connector);
            for (int i = 0; i < Output.Values.Count; i++)
            {
                Output[i].YRatio = (i + 1.0) / (Output.Values.Count + 1.0);
            }
            AddConnector(connector);
        }

        public virtual void ExecuteAddBottomOutput(object parameter)
        {
            FullyCreatedConnectorInfo connector = new FullyCreatedConnectorInfo(this, ConnectorOrientation.Bottom, true);
            connector.YRatio = 1;
            Output.Add(Output.Count, connector);
            for (int i = 0; i < Output.Values.Count; i++)
            {
                Output[i].XRatio = (i + 1.0) / (Output.Values.Count + 1.0);
                if (Input.ContainsKey(i))
                {
                    Input[i].XRatio = Output[i].XRatio;
                }
            }

            AddConnector(connector);
        }

        public virtual void ExecuteAddActionOutput(object parameter)
        {
            FullyCreatedConnectorInfo connector = new FullyCreatedConnectorInfo(this, ConnectorOrientation.Right, true);
            connector.XRatio = 1;
            Action.Add(Action.Count, connector);
            Action[Action.Count - 1].YRatio = 0.5;
            AddConnector(connector);
        }

        [Browsable(false)]
        public SFCNodeKinds Kind { get; set; }

        private double _value;
        public double Value
        {
            get
            {
                return _value;
            }
            set
            {
                SetProperty(ref _value, value);
            }
        }

        private string _expression;
        public string Expression
        {
            get
            {
                return _expression;
            }
            set
            {
                SetProperty(ref _expression, value);
            }
        }

        #region 暂不保存
        private int _status;

        public int Status
        {
            get { return _status; }
            set
            {
                SetProperty(ref _status, value);
            }
        }

        public List<SFCNode> NextNode { get; set; } = new List<SFCNode>();
        public List<SFCNode> PreNode { get; set; } = new List<SFCNode>();
        #endregion
    }
}
