using Godot;
using System;
using System.Collections.Generic;

public partial class ActionQueueUIHandler : VBoxContainer
{
        private PackedScene template;
        private List<QueueActionDisplay> rows;
        //private Dictionary<int, int> indexes;

        private int threadsPtr = 0;
        private int _size = 0;

        public override void _Ready()
        {
                rows = new List<QueueActionDisplay>(GameManager.Instance.MaxThreads);
                template = GD.Load<PackedScene>("res://scenes/ui/queue_action.tscn");

                GameManager.Instance.Queued += _UpdateActionQueued;
                GameManager.Instance.DeQueued += _UpdateActionDeQueued;
                GameManager.Instance.MaxThreadsModified += _MaxThreadChanged;
                GameManager.Instance.AllActionsApplied += _Clear;

                _size = GameManager.Instance.MaxThreads;
                threadsPtr = 0;
                for (int i = 0; i < GameManager.Instance.MaxThreads; i++)
                {
                        _Instantiate(i, "<Empty>", null);
                }
        }

        public override void _ExitTree()
        {
                GameManager.Instance.Queued -= _UpdateActionQueued;
                GameManager.Instance.DeQueued -= _UpdateActionDeQueued;
                GameManager.Instance.MaxThreadsModified -= _MaxThreadChanged;
                GameManager.Instance.AllActionsApplied -= _Clear;
        }

        private void _Instantiate(int i, string name, Node reference)
        {
                QueueActionDisplay tmp = template.Instantiate<QueueActionDisplay>();
                AddChild(tmp);
                tmp.Name = "ThreadActionUI_" + i.ToString();
                tmp.set_data(i, name, reference);
                rows.Add(tmp);
        }

        private void _MaxThreadChanged(int _newNum)
        {
                GD.Print("Executing MaxThreadChanged");
                _RemoveAll();

                _size = GameManager.Instance.MaxThreads;
                rows.EnsureCapacity(_size);
                for (int i = 0; i < _newNum; i++)
                {
                        _Instantiate(i, "<Empty>", null);
                }
        }

        private void _Clear()
        {
                for (int i = 0; i < _size; i++)
                {
                        rows[i].clear_data();
                }
                threadsPtr = 0;
        }

        private void _RemoveAll()
        {
                foreach (QueueActionDisplay row in rows)
                {
                        row.QueueFree();
                        RemoveChild(row);
                }
                rows.Clear();
                threadsPtr = 0;
        }

        private void _UpdateActionQueued(string name, Node @ref)
        {
                rows[threadsPtr].set_data(threadsPtr, name, @ref);
                threadsPtr++;
        }

        private void _UpdateActionDeQueued(Node @ref)
        {
                QueueActionDisplay tmp = null;
                foreach (QueueActionDisplay row in rows)
                        if (row.link == @ref)
                        {
                                tmp = row;
                                break;
                        }

                if (tmp == null) { return; }

                rows.Remove(tmp);
                tmp.QueueFree();
                RemoveChild(tmp);
                threadsPtr--;

                for (int i = 0; i < rows.Count; i++)
                {
                        rows[i].set_index(i);
                }

                _Instantiate(_size - 1, "<Empty>", null);
        }
}
