using RobotNet.MapShares.Dtos;

namespace RobotNet.WebApp.Maps.Models;

public class MapNodeModel : IEnumerable<NodeModel>
{
    private readonly Dictionary<Guid, NodeModel> dicNodes = [];
    public NodeModel this[int i] => dicNodes.Values.ElementAt(i);
    public NodeModel this[Guid id] => dicNodes[id];
    public IEnumerator<NodeModel> GetEnumerator() => dicNodes.Values.GetEnumerator();
    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();
    public bool ContainsKey(Guid key) => dicNodes.ContainsKey(key);
    public bool TryGetValue(Guid id, out NodeModel? value) => dicNodes.TryGetValue(id, out value);

    public NodeModel? SelectedNode { get; set; }
    public List<NodeModel> ActivedNodes { get; private set; } = [];

    public event Action? Changed;

    private (double X, double Y) StartMovePosition;

    public void Add(NodeDto node)
    {
        if (dicNodes.ContainsKey(node.Id)) return;

        var model = new NodeModel(node);
        dicNodes.Add(model.Id, model);
        Changed?.Invoke();
    }

    public void ReplaceAll(IEnumerable<NodeDto> nodes)
    {
        dicNodes.Clear();

        foreach (var node in nodes)
        {
            var model = new NodeModel(node);
            dicNodes.Add(model.Id, model);
        }
        Changed?.Invoke();
    }

    public void Remove(NodeModel node)
    {
        if (!dicNodes.ContainsKey(node.Id)) return;

        node.Dispose();
        dicNodes.Remove(node.Id);
        Changed?.Invoke();
    }

    public void ActivedNode(IEnumerable<NodeModel> nodes)
    {
        UnActivedNode();
        foreach (var node in nodes)
        {
            var nodeInDic = dicNodes.Values.FirstOrDefault(e => e.Id.Equals(node.Id));
            nodeInDic?.Active();
            ActivedNodes.Add(node);
        }
    }
    public void UnActivedNode()
    {
        foreach (var node in ActivedNodes)
        {
            var nodeInDic = dicNodes.Values.FirstOrDefault(e => e.Id.Equals(node.Id));
            nodeInDic?.UnActive();
        }
        ActivedNodes.Clear();
    }

    public void SetStartMovePosition(double x, double y)
    {
        StartMovePosition.X = x;
        StartMovePosition.Y = y;
    }

    public void UpdateMoveNode(double x, double y)
    {
        double deltaX = x - StartMovePosition.X;
        double deltaY = y - StartMovePosition.Y;
        ActivedNodes.ForEach(n => n.UpdatePosition(n.X + deltaX, n.Y + deltaY));
        StartMovePosition.X = x;
        StartMovePosition.Y = y;
    }
}
