using DunGen;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using UnityEngine;

namespace MuzikaGromche
{
    public class DiscoBallManager : MonoBehaviour
    {
        // A struct holding a disco ball container object and the name of a tile for which it was designed.
        public readonly record struct Data(string TileName, GameObject DiscoBallContainer)
        {
            // We are specifically looking for cloned tiles, not the original prototypes.
            public readonly string TileCloneName = $"{TileName}(Clone)";
        }

        public static readonly List<Data> Containers = [];
        private static readonly List<GameObject> InstantiatedContainers = [];

        public static void Initialize()
        {
            string bundlePath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "muzikagromche_discoball");
            var bundle = AssetBundle.LoadFromFile(bundlePath);

            foreach ((string prefabPath, string tileName) in new[] {
                ("Assets/LethalCompany/Mods/MuzikaGromche/DiscoBallContainerManor.prefab", "ManorStartRoomSmall"),
                ("Assets/LethalCompany/Mods/MuzikaGromche/DiscoBallContainerManorOLD.prefab", "ManorStartRoom"),
                ("Assets/LethalCompany/Mods/MuzikaGromche/DiscoBallContainerFactory.prefab", "StartRoom"),
                ("Assets/LethalCompany/Mods/MuzikaGromche/DiscoBallContainerMineShaft.prefab", "MineshaftStartTile"),
                ("Assets/LethalCompany/Mods/MuzikaGromche/DiscoBallContainerLargeForkTileB.prefab", "LargeForkTileB"),
                ("Assets/LethalCompany/Mods/MuzikaGromche/DiscoBallContainerBirthdayRoomTile.prefab", "BirthdayRoomTile"),
            })
            {
                var container = bundle.LoadAsset<GameObject>(prefabPath);
                Containers.Add(new(tileName, container));
            }
        }

        public static void Enable()
        {
            // Just in case
            Disable();

            var query = from tile in Resources.FindObjectsOfTypeAll<Tile>()
                        join container in Containers
                        on tile.gameObject.name equals container.TileCloneName
                        select (tile, container);

            foreach (var (tile, container) in query)
            {
                Enable(tile, container);
            }
        }

        private static readonly string[] animatorNames = [
            "DiscoBallProp/AnimContainer",
            "DiscoBallProp1/AnimContainer",
            "DiscoBallProp2/AnimContainer",
            "DiscoBallProp3/AnimContainer",
            "DiscoBallProp4/AnimContainer",
            "DiscoBallProp5/AnimContainer",
        ];

        private static void Enable(Tile tile, Data container)
        {
            Debug.Log($"{nameof(MuzikaGromche)} {nameof(DiscoBallManager)} Enabling at '{tile.gameObject.name}'");
            var discoBall = Instantiate(container.DiscoBallContainer, tile.transform);
            InstantiatedContainers.Add(discoBall);

            foreach (var animatorName in animatorNames)
            {
                if (discoBall.transform.Find(animatorName)?.gameObject is GameObject animator)
                {
                    animator.GetComponent<Animator>().SetBool("on", true);
                }
            }
        }

        public static void Disable()
        {
            foreach (var discoBall in InstantiatedContainers)
            {
                Debug.Log($"{nameof(MuzikaGromche)} {nameof(DiscoBallManager)}: Disabling {discoBall.name}");
                Destroy(discoBall);
            }
            InstantiatedContainers.Clear();
        }
    }
}
