using System.Collections.Generic;
using System.Windows;
using AIStudio.Wpf.DiagramDesigner.Geometrys;

namespace AIStudio.Wpf.DiagramDesigner.Layout
{
    internal interface IState
    {
        VectorBase GetNodePosition(DesignerItemViewModelBase node);
        void SetNodePosition(DesignerItemViewModelBase node, VectorBase pos);
        VectorBase GetEndpointPosition(ConnectorInfoBase endpoint);
        VectorBase GetNodeSpeed(DesignerItemViewModelBase node);
        void SetNodeSpeed(DesignerItemViewModelBase node, VectorBase speed);
    }

    internal class BufferedState : IState
    {
        private readonly Dictionary<DesignerItemViewModelBase, VectorBase> _nodePositions = new Dictionary<DesignerItemViewModelBase, VectorBase>();
        private readonly Dictionary<ConnectorInfoBase, VectorBase> _endpointRelativePositions = new Dictionary<ConnectorInfoBase, VectorBase>();
        public IEnumerable<KeyValuePair<DesignerItemViewModelBase, VectorBase>> NodePositions => _nodePositions;

        private readonly Dictionary<DesignerItemViewModelBase, VectorBase> _nodeSpeeds = new Dictionary<DesignerItemViewModelBase, VectorBase>();

        public VectorBase GetNodePosition(DesignerItemViewModelBase node)
        {
            if (!_nodePositions.TryGetValue(node, out VectorBase result))
            {
                result = new VectorBase(node.Position.X, node.Position.Y);
            }

            return result;
        }

        public void SetNodePosition(DesignerItemViewModelBase node, VectorBase pos)
        {
            _nodePositions[node] = pos;
        }

        public VectorBase GetEndpointPosition(ConnectorInfoBase endpoint)
        {
            if (!_endpointRelativePositions.TryGetValue(endpoint, out VectorBase result))
            {
                result = new VectorBase(endpoint.MiddlePosition.X, endpoint.MiddlePosition.Y) - GetNodePosition(endpoint.Parent as DesignerItemViewModelBase);
                _endpointRelativePositions[endpoint] = result;
            }

            return result + GetNodePosition(endpoint.Parent as DesignerItemViewModelBase);
        }

        public VectorBase GetNodeSpeed(DesignerItemViewModelBase node)
        {
            if (!_nodeSpeeds.TryGetValue(node, out VectorBase result))
            {
                result = new VectorBase(0, 0);
            }

            return result;
        }

        public void SetNodeSpeed(DesignerItemViewModelBase node, VectorBase speed)
        {
            _nodeSpeeds[node] = speed;
        }
    }

    internal class LiveState : IState
    {
        private readonly Dictionary<DesignerItemViewModelBase, VectorBase> _nodeSpeeds = new Dictionary<DesignerItemViewModelBase, VectorBase>();

        public VectorBase GetNodePosition(DesignerItemViewModelBase node)
        {
            return new VectorBase(node.Position.X, node.Position.Y);
        }

        public void SetNodePosition(DesignerItemViewModelBase node, VectorBase pos)
        {
            node.Position = new Point(pos.X, pos.Y);
        }

        public VectorBase GetEndpointPosition(ConnectorInfoBase endpoint)
        {
            return new VectorBase(endpoint.MiddlePosition.X, endpoint.MiddlePosition.Y);
        }

        public VectorBase GetNodeSpeed(DesignerItemViewModelBase node)
        {
            if (!_nodeSpeeds.TryGetValue(node, out VectorBase result))
            {
                result = new VectorBase(0, 0);
            }

            return result;
        }

        public void SetNodeSpeed(DesignerItemViewModelBase node, VectorBase speed)
        {
            _nodeSpeeds[node] = speed;
        }
    }
}
