using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using UnityEngine.SceneManagement;
using DG.Tweening;
using System;
using System.Globalization;
using UnityEngine.Events;

public class FloorComplete : MonoBehaviour
{
	[SerializeField] private Upgrade rerollUpgrade;
	[SerializeField] private Button rerollButton;
	[SerializeField] private TMP_Text rerollsLeftText;
	private int timesCanReroll = 0;
	private bool canReroll = false;
	[SerializeField] private AudioClip reRollPressedClip;
	[System.NonSerialized] public UnityEvent onReroll = new();
	private int totalPurchases = 0;

	[SerializeField] private Animator endRoomExitDoor;
	private AudioSource exitDoorSource;
	private bool finishedPickingUpgrades;

	[SerializeField] private Transform UpgradeContainer;
	[SerializeField] private TMP_Text playerCoinsText;
	[SerializeField] private Button skipButton;
	[SerializeField] private TMP_Text skipButtonText;

	[Space]

	[SerializeField] private GameObject FloorCompleteStatsContainer;
	[SerializeField] private GameObject floorCompleteCanvas;
	[SerializeField] private Image backgroundImage;
	[SerializeField] private CanvasGroup MainContainerGroup;

	[Space]

	[SerializeField] private TMP_Text floorNumber;
	[SerializeField] private TMP_Text completionTime_Value;
	[SerializeField] private TMP_Text enemiesInFloor_Value;
	[SerializeField] private TMP_Text killsInFloor_Value;
	[SerializeField] private TMP_Text totalKills_Value;

	[Space]

	[SerializeField] private Button goToNextFloor_Button;
	[SerializeField] private Button exitDungeon_Button;

	[Space]

	//tween Objects
	[SerializeField] private GameObject banner;
	[SerializeField] private GameObject statsContainer;
	[SerializeField] private GameObject buttonContainer;

	[Space]

	[SerializeField] private GameObject ExitDungeonUI;
	private CanvasGroup ExitUIGroup;
	[SerializeField] private Button YesButton;
	[SerializeField] private Button NoButton;

	[System.NonSerialized] public readonly Queue<Upgrade> generatedUpgrades = new();
	private List<Upgrade> generatedUpgradesList = new();
	private static readonly int OpenDoor = Animator.StringToHash("OpenDoor");

	private void Awake()
	{
		ExitUIGroup = ExitDungeonUI.GetComponent<CanvasGroup>();
		ExitDungeonUI.SetActive(false);
		floorCompleteCanvas.SetActive(false);
		exitDoorSource = endRoomExitDoor.GetComponent<AudioSource>();

		rerollButton.onClick.AddListener(OnRerollPressed);
		goToNextFloor_Button.onClick.AddListener(GoToNextFloor);
		exitDungeon_Button.onClick.AddListener(() => SwitchUI(true));
		NoButton.onClick.AddListener(PressedNoButton);
		YesButton.onClick.AddListener(PressedYesButton);
		skipButton.onClick.AddListener(SkipUpgrades);
		backgroundImage.color = Color.clear;

		banner.transform.localScale = Vector3.zero;
		statsContainer.transform.localScale = Vector3.zero;
		buttonContainer.transform.localScale = Vector3.zero;
		UpgradeContainer.localScale = new Vector3(1, 0, 1);

	}

	private void Start()
	{
		canReroll = GameManager.Instance.SaveData.HasUpgrade(rerollUpgrade);
		timesCanReroll = canReroll ? GameManager.Instance.SaveData.GetUpgradeCount(rerollUpgrade) : 0;
		rerollButton.transform.localScale = Vector3.zero;

		rerollButton.gameObject.SetActive(canReroll);
		if (canReroll)
		{
			rerollsLeftText.text = timesCanReroll.ToString();
			rerollButton.transform.DOScale(Vector3.one, 0.2f).SetEase(Ease.OutBack).SetUpdate(true);
		}

		GenerateUpgrades();
	}

	public TMP_Text GetPlayerCoinsText() => playerCoinsText;
	public TMP_Text GetSkipButtonText() => skipButtonText;

	private void OnTriggerEnter(Collider other)
	{
		if (other.CompareTag("Player"))
		{
			StartCoroutine(StartEvent());
		}
	}

	private void SkipUpgrades() => finishedPickingUpgrades = true;
	private void GenerateUpgrades()
	{
		if (timesCanReroll <= 0)
		{
			rerollButton.gameObject.SetActive(false);
		}

		//generate the upgrades for this floor
		for (int i = 0; i < 3; i++)
		{
			Upgrade upgrade = UpgradeManager.Instance.GetRandom();
			UpgradeManager.Instance.UsableUpgrades.Remove(upgrade);
			generatedUpgradesList.Add(upgrade);
			generatedUpgrades.Enqueue(upgrade);
		}
	}

	private void OnRerollPressed()
	{
		UpgradeManager.Instance.UsableUpgrades.AddRange(generatedUpgradesList);
		generatedUpgradesList.Clear();
		Debug.LogError("Amount of usable upgrades: " + UpgradeManager.Instance.UsableUpgrades.Count);

		generatedUpgrades.Clear();
		timesCanReroll--;
		rerollsLeftText.text = timesCanReroll.ToString();
		GenerateUpgrades();
		onReroll?.Invoke();

		SoundEffectOptions options = SoundEffectOptions.Default;
		options.clip = reRollPressedClip;
		options.loop = false;
		options.is3D = false;
		options.randomizePitch = true;
		options.volume = 0.1f;
		options.repoolAfterPlay = true;
		GameManager.Instance.CreateAndPlaySoundEffect(options);

	}

	public void PurchasedUpgrade()
	{
		totalPurchases++;
		if(totalPurchases >= 3)
		{
			rerollButton.gameObject.SetActive(false);
		}
	}

	private IEnumerator StartEvent()
	{
		GameManager.Instance.FinishedFloor = true;
		playerCoinsText.SetText($"{GameManager.Instance.SaveData.Coins}");
		GameManager.Instance.GetAudioManager().StopMusicWithFadeOut(true);
		backgroundImage.DOFade(1.0f, 0.3f).SetEase(Ease.InSine).OnComplete(() =>
		{
			banner.transform.DOScale(Vector3.one, 0.25f).SetEase(Ease.InSine).OnComplete(() =>
			{
				UpgradeContainer.DOScaleY(1, 0.25f);
			});
		});

		floorNumber.SetText($"{GameManager.Instance.SaveData.FloorNum}");

		FloorCompleteStatsContainer.SetActive(false);
		floorCompleteCanvas.SetActive(true);
		GameManager.Instance.LockCursor(false);

		PlayerStats.Instance.CanLook = false;
		PlayerStats.Instance.PlayerController.canMove = false;
		WeaponSystem playerWeapon = PlayerStats.Instance.WeaponSlot.GetComponentInChildren<WeaponSystem>();
		playerWeapon.enabled = false;

		endRoomExitDoor.SetBool(OpenDoor, true);
		exitDoorSource.Play();

		yield return new WaitUntil(() => finishedPickingUpgrades);

		UpgradeContainer.gameObject.SetActive(false);
		FloorCompleteStatsContainer.SetActive(true);
		SetTweensAndData();
	}

	private void SetTweensAndData()
	{
		int previousTotalKills = GameManager.Instance.SaveData.TotalKills - GameManager.Instance.killsPerFloor;
		completionTime_Value.text = "00:00:00";
		enemiesInFloor_Value.text = "0";
		killsInFloor_Value.text = "0";
		totalKills_Value.SetText($"{previousTotalKills}");

		statsContainer.transform.DOScale(Vector3.one, 0.25f).SetEase(Ease.InSine).SetDelay(0.1f);
		buttonContainer.transform.DOScale(Vector3.one, 0.25f).SetEase(Ease.InSine).SetDelay(0.2f);

		//data assignment
		StartCoroutine(CountUpStats(0.5f, completionTime_Value, 0, PlayerStats.Instance.GetFloorTime(), 0.2f, true));
		StartCoroutine(CountUpStats(0.6f, enemiesInFloor_Value, 0, GameManager.Instance.maxEnemiesInDungeon, 0.2f));
		StartCoroutine(CountUpStats(0.7f, killsInFloor_Value, 0, GameManager.Instance.killsPerFloor, 0.2f));
		StartCoroutine(CountUpStats(0.8f, totalKills_Value, previousTotalKills, GameManager.Instance.SaveData.TotalKills, 0.2f));
	}



	private IEnumerator CountUpStats(float delay, TMP_Text textToChange, float startingValue, float endingValue, float maxTimeAllowedPerIteration, bool isTimeSpan = false)
	{
		yield return new WaitForSeconds(delay);
		TimeSpan ts = TimeSpan.FromSeconds(PlayerStats.Instance.GetFloorTime());
		string timeToComplete = $"{ts.TotalHours:00}:{ts.TotalMinutes:00}:{ts.Seconds:00}";

		float duration = 0;
		while (duration < 1)
		{

			int statToCount = Mathf.FloorToInt(Mathf.Lerp(startingValue, endingValue, duration));
			TimeSpan statToCountTS = TimeSpan.FromSeconds(statToCount);
			textToChange.text = isTimeSpan ? $"{statToCountTS.TotalHours:00}:{statToCountTS.TotalMinutes:00}:{statToCountTS.Seconds:00}"
				: statToCount.ToString();

			duration += Time.deltaTime / maxTimeAllowedPerIteration;
			yield return null;
		}

		textToChange.text = isTimeSpan ? timeToComplete : endingValue.ToString(CultureInfo.InvariantCulture);

		textToChange.transform.DOPunchScale(Vector3.one * 0.5f, 0.25f, 2);
	}

	private static void GoToNextFloor()
	{
		GameManager.Instance.SaveData.FloorNum++;
		GameManager.Instance.GetSaveManager().UpdateSaveData();
		GameManager.Instance.GetSaveManager().UpdateSettingsSaveData();

		if (GameManager.Instance.SaveData.FloorNum % 10 == 0)
		{
			SceneManager.LoadScene("BossRoom_01");
		}
		else
		{
			SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
		}

	}

	private static IEnumerator FadeUI(CanvasGroup GroupToFade, float startAlpha, float endAlpha, bool disableAtEnd = false, float maxTime = 2f)
	{
		GroupToFade.gameObject.SetActive(true);
		GroupToFade.alpha = startAlpha;

		GroupToFade.blocksRaycasts = startAlpha != 1;

		float duration = 0f;
		while (duration <= 1)
		{
			GroupToFade.alpha = Mathf.Lerp(startAlpha, endAlpha, duration);
			duration += Time.deltaTime / maxTime;
			yield return null;
		}

		GroupToFade.alpha = endAlpha;// to make sure after lerping it is assigned to the end alpha.

		if (disableAtEnd)
		{
			GroupToFade.gameObject.SetActive(false);
		}
	}

	private void SwitchUI(bool mainFadeOut)
	{
		float lhs = mainFadeOut ? 1f : 0f;
		float rhs = mainFadeOut ? 0f : 1f;

		StartCoroutine(FadeUI(MainContainerGroup, lhs, rhs, false, 0.2f));
		StartCoroutine(FadeUI(ExitUIGroup, rhs, lhs, false, 0.2f));
	}

	private void PressedNoButton()
	{
		SwitchUI(false);
	}

	private static void PressedYesButton()
	{
		Debug.Log("Quitting Application.");
		Application.Quit();
	}


}