using Nox.Core;
using Nox.Game;
using Jovian.SaveSystem;
using Nox.Game.UI;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;

namespace Nox.UI {
    /// <summary>
    /// Main menu interface class which is responsible for creating the main menu view and handling the main menu events
    /// </summary>
    public class MainMenuView : IGameLifecycle, IMenuView {
        private readonly MenuPrefabsContainer menuPrefabsContainer;
        private readonly MenuGameStateData menuGameStateData;
        private readonly ISaveSystem saveSystem;
        private readonly GameDataState gameDataState;
        private readonly PartySettings partySettings;
        private readonly ICharacterSystems characterSystems;
        private readonly PortraitsHolder portraitsHolder;
        private MainMenuReference mainMenuReference;
        private CharacterCreationReference characterCreationReference;
        private CharacterCreationView characterCreationView;
        private AsyncOperationHandle<GameObject> charCreationHandle;
        private readonly StarterCharacterSettings starterCharacterSettings;

        public MainMenuView(MenuPrefabsContainer menuPrefabsContainer,
            MenuGameStateData menuGameStateData,
            ISaveSystem saveSystem,
            GameDataState gameDataState,
            PartySettings partySettings,
            ICharacterSystems characterSystems,
            PortraitsHolder portraitsHolder,
            StarterCharacterSettings starterCharacterSettings) {
            this.menuPrefabsContainer = menuPrefabsContainer;
            this.menuGameStateData = menuGameStateData;
            this.saveSystem = saveSystem;
            this.gameDataState = gameDataState;
            this.partySettings = partySettings;
            this.characterSystems = characterSystems;
            this.portraitsHolder = portraitsHolder;
            this.starterCharacterSettings = starterCharacterSettings;
        }
        public void Initialize() {
            if(!mainMenuReference) {
                mainMenuReference = Addressables.InstantiateAsync(menuPrefabsContainer.mainMenuReference).WaitForCompletion().GetComponent<MainMenuReference>();
            }
            mainMenuReference.exitButton.onClick.AddListener(Application.Quit);
            mainMenuReference.optionsButton.onClick.AddListener(() => {/* options logic here */});
            mainMenuReference.newGameButton.onClick.AddListener(InitializeCharacterCreation);

            bool hasSave = saveSystem.HasAnySaves();
            mainMenuReference.continueButton.gameObject.SetActive(hasSave);
            if(hasSave) {
                mainMenuReference.continueButton.onClick.AddListener(() => menuGameStateData.continueGameRequest.Invoke());
            }
            Show();
        }

        public void Show() {
            mainMenuReference.gameObject.SetActive(true);
        }
        public void Hide() {
            mainMenuReference.gameObject.SetActive(false);
        }

        private void InitializeCharacterCreation() {
            charCreationHandle = Addressables.InstantiateAsync(menuPrefabsContainer.characterCreationReference);
            var result = charCreationHandle.WaitForCompletion();
            characterCreationReference =result.GetComponent<CharacterCreationReference>();
            characterCreationView = new CharacterCreationView(
                characterCreationReference,
                menuGameStateData,
                saveSystem,
                gameDataState,
                partySettings,
                characterSystems,
                portraitsHolder,
                starterCharacterSettings);
            characterCreationView.Initialize();
            characterCreationView.Show();
        }

        public void Tick() {
            characterCreationView?.Tick();
        }

        public void Dispose() {
            characterCreationView?.Dispose();
            Object.Destroy(characterCreationReference?.gameObject);
            if (charCreationHandle.IsValid()) {
                charCreationHandle.Release();
            }
        }
    }
}
