using System.Collections.Generic;
using Sirenix.OdinInspector;
using UnityEngine;
using VOID.Generic;
using VOID.Generic.Objects.Unit;
using VOID.Generic.Objects.Unit.Actions;
using VOID.Generic.Objects.Usable;
using VOID.Generic.Objects.Usable.Events;
using VOID.Generic.Player;
using VOID.Generic.Util;
using VOID.ScriptableObjects;
using VOID.UserInterface.Generic.Lobby;

namespace VOID.Lobby
{
    public class LobbyGameStarterManager : MonoBehaviour
    {
        [SerializeField, Required] private UsableObject _startObject;
        [SerializeField, RequiredListLength(MinLength = 1)] private List<UnitGenerator> _unitGenerators = new();
        [SerializeField, RequiredListLength(MinLength = 1)] private List<Transform> _generatePositions = new();

        [SerializeField] private int _generateCount = 3;
        private Dictionary<UnitObject, Transform> _generatedUnits = new();

        private void Start()
        {
            if (_generateCount > _generatePositions.Count)
            {
                _generateCount = _generatePositions.Count;
                Debug.LogWarning($"Not enough position ({_generatePositions.Count}) to generate {_generateCount} units");
            }

            // Initialize units
            RandomUtil.RandomElements(_generatePositions, _generateCount).ForEach(position =>
            {
                var unit = RandomUtil.RandomElement(_unitGenerators).Generate();
                unit.transform.SetPositionAndRotation(position.position, position.rotation);
                _generatedUnits.Add(unit, position);
                LobbyGameStarterUI.current.AddUnit(unit, SelectUnit);
            });
            
            // 1. Check if game start is possible
            // 2. Start game
            _startObject.usableEvents.onUsedBefore.AddListener(CanStartGame);
            _startObject.usableEvents.onUsedAfter.AddListener(StartGame);
        }

        private void SelectUnit(UnitObject unit)
        {
            // Make previous unit go back to its original position and wait
            var previousUnit = PlayerController.current.mainUnit;
            if (previousUnit)
            {
                previousUnit.OrderStop();
                previousUnit.OrderChain(new List<AbstractAction>()
                {
                    new MoveAction(previousUnit, _generatedUnits[previousUnit].position),
                    new RotateAction(previousUnit, _generatedUnits[previousUnit].rotation.y)
                });
            }
            
            PlayerController.current.SetMainUnit(unit);
            PlayerController.current.SetMainUnitActive();
        }

        private void CanStartGame(UseEvent useEvent)
        {
            // Trying to start game without selecting avatar
            if (!PlayerController.current.mainUnit) useEvent.prevented = true;
        }

        private void StartGame(UseEvent useEvent)
        {
            GameLoopManager.current.LoadGenerator(PlayerController.current.mainUnit);
        }
    }
}