using System.Collections.Generic;
using UnityEngine;

public class WeaponSwitcher : MonoBehaviour
{
    public float switchCooldown = 0.2f;

    public Gun CurrentGun { get; private set; }

    private readonly List<Gun> _weapons = new List<Gun>();
    private HUDController _hud;
    private int _currentIndex = -1;

    private void Start()
    {
        if (_hud == null)
        {
            _hud = FindObjectOfType<HUDController>();
        }

        if (_weapons.Count == 0)
        {
            DiscoverWeapons();
        }
    }

    public void Initialize(IEnumerable<Gun> weapons, HUDController hud)
    {
        _weapons.Clear();
        _weapons.AddRange(weapons);
        _hud = hud;

        for (int i = 0; i < _weapons.Count; i++)
        {
            if (_weapons[i] != null)
            {
                _weapons[i].BindOwnership(_hud, this);
                _weapons[i].gameObject.SetActive(false);
            }
        }

        SelectWeapon(0, true);
    }

    private void Update()
    {
        if (_weapons.Count == 0)
        {
            DiscoverWeapons();
        }

        if (_weapons.Count == 0)
        {
            return;
        }

        if (Input.GetKeyDown(KeyCode.Alpha1))
        {
            SelectWeapon(0);
        }

        if (Input.GetKeyDown(KeyCode.Alpha2))
        {
            SelectWeapon(1);
        }

        if (Input.GetKeyDown(KeyCode.Alpha3))
        {
            SelectWeapon(2);
        }

        float mouseWheel = Input.GetAxis("Mouse ScrollWheel");
        if (mouseWheel > 0.05f)
        {
            SelectWeapon((_currentIndex + 1) % _weapons.Count);
        }
        else if (mouseWheel < -0.05f)
        {
            SelectWeapon((_currentIndex - 1 + _weapons.Count) % _weapons.Count);
        }
    }

    public bool AddAmmoToCurrentWeapon(int amount)
    {
        return CurrentGun != null && CurrentGun.AddReserveAmmo(amount);
    }

    public void RefreshHud()
    {
        if (CurrentGun == null || _hud == null)
        {
            return;
        }

        _hud.SetWeapon(CurrentGun.weaponName);
        _hud.SetAmmo(CurrentGun.AmmoInMagazine, CurrentGun.ReserveAmmo);
    }

    private void SelectWeapon(int index, bool force = false)
    {
        if (_weapons.Count == 0 || index < 0 || index >= _weapons.Count)
        {
            return;
        }

        if (!force && index == _currentIndex)
        {
            return;
        }

        for (int i = 0; i < _weapons.Count; i++)
        {
            if (_weapons[i] == null)
            {
                continue;
            }

            if (i != index)
            {
                _weapons[i].CancelReload();
                _weapons[i].gameObject.SetActive(false);
            }
        }

        _currentIndex = index;
        CurrentGun = _weapons[_currentIndex];

        if (CurrentGun != null)
        {
            CurrentGun.gameObject.SetActive(true);
            CurrentGun.SetEquipCooldown(force ? 0f : switchCooldown);
        }

        RefreshHud();
    }

    private void DiscoverWeapons()
    {
        _weapons.Clear();
        Gun[] foundWeapons = GetComponentsInChildren<Gun>(true);
        for (int i = 0; i < foundWeapons.Length; i++)
        {
            _weapons.Add(foundWeapons[i]);
            foundWeapons[i].BindOwnership(_hud, this);
            foundWeapons[i].gameObject.SetActive(false);
        }

        if (_weapons.Count > 0)
        {
            SelectWeapon(0, true);
        }
    }
}
