using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using System;


public class RewardsManager : MonoBehaviour {
    public Slider levelBar; //Slider showing the level based on XP
    public TMP_Text XP_show; // Reference to the XP TextMeshPro component
    public TMP_Text level_value; // Reference to the level TextMeshPro component
    public TMP_Text rank_value; // Reference to the rank TextMeshPro component
    public TMP_Text rank_level_UI; // Reference to the InputField component

    int current_level;
    int x_value;

    // References to PLAYERPREFS Key for the Player's Rewards Data
    private const string player_RewardsData = "Player_RewardsData";

    private PlayerData playerData; // List of character information


    //Loads and updates XP at component creation.
    private void Awake(){
        // Load player data and update text field immediately upon component creation
        LoadAndUpdateXP();
    }

    //Loads and updates XP when component becomes enabled.
    private void OnEnable(){
        // Load player data and update text field when component becomes enabled
        LoadAndUpdateXP();
    }

    //Loads PlayerData and updates the XP text field.
    private void LoadAndUpdateXP(){
        // Load player data
        PlayerData retrieved_playerData = LoadPlayerData();
        int player_xp = retrieved_playerData.xp;

        if (player_xp < 0){
            player_xp = 0;
            retrieved_playerData.xp = 0;
            SavePlayerData(retrieved_playerData);
        }

        // Update the text field
        UpdateTextMeshProValue(player_xp.ToString());
    }


    //Initializes PlayerData, sets up UI text, and subscribes to InputField change events.
    private void Start(){

        // If already there's rewards data saved
        if (PlayerPrefs.HasKey(player_RewardsData)){
            playerData = LoadPlayerData();

        }else{ //no rewards data saved, start somewhere, save and load
            playerData = new PlayerData { xp = 0, rank = "Bronze", prevRank = "Bronze", overall_matches = 0, win_streak = 0, loss_streak = 0, overall_wins = 0, overall_losses = 0, rank_level = 1, prevrank_level = 1,
                rank_game = 0, eliminations = 0, deaths = 0, revives = 0 };

            SavePlayerData(playerData); //Saves the player's mission_progress data
            playerData = LoadPlayerData();
        }

        if (playerData.rank != playerData.prevRank){
            Debug.Log("There has been change in the Rank");
        }

        rank_level_UI.text = "Level " + playerData.rank_level;       
        rank_value.text = playerData.rank;

    }


    // Function called whenever the value of the InputField changes
    private void UpdateTextMeshProValue(string newValue){
        // Update the TextMeshPro text with the new value
        if (int.Parse(newValue) != 0){
            StartCoroutine(AnimateTextMeshProValue(newValue));
        }else{
            XP_show.text = newValue;
        }

        //There is an alternative way of doing this
        int intValue = int.Parse(newValue);

        // Define level ranges
        int[] levelRanges = { 100, 2650, 3900, 4750, 5600, 6350, 7100, 7850, 8150, 8600, 9050, 9500, 9950, 10400, 10850,
            11300, 11750, 12200, 12350, 12500, 12650, 12800, 12950, 13100, 13250, 13400, 13550, 13700, 13850, 14000,
            14150, 14300, 14450, 14600, 14750, 14900, 15050, 15200, 15350, 15500, 15650, 15800, 15950, 16100, 16250,
            16400, 16550, 16700, 16850, 17000, 17150, 17300, 17450, 17600, 17750, 17900, 18000 };

        for (int i = 0; i < levelRanges.Length; i++){
            if (intValue <= levelRanges[i]){
                if (intValue < 100){
                    current_level = i + 1;
                }

                // if (intValue == levelRanges[i]){
                if (intValue == levelRanges[i]){
                    current_level = i + 1;
                }

                if ((intValue != levelRanges[i]) && !(intValue < 100)){
                    current_level = i;
                }
                break;
            }
        }

        if (current_level != 1){
            //Create animation
            StartCoroutine(Animate_LevelValue(current_level.ToString()));
        }else{
            level_value.text = current_level.ToString();   
        }

        x_value = Mathf.Clamp(current_level, 1, 58);
        float normalizedValue = Mathf.Clamp01((float)x_value / 58f);

        // Set the normalized value to the Slider
        if (current_level != 0){
            levelBar.StartCoroutine(AnimateSliderValue(normalizedValue));   
        }else{
            levelBar.value = normalizedValue;
        }
    }


    // Create Slider animation coroutine
    private IEnumerator AnimateSliderValue(float targetValue){
        float animationDuration = 1.0f; // You can adjust the duration of the animation
        float startValue = 0;

        for (float t = 0f; t < 1.0f; t += Time.deltaTime / animationDuration)
        {
            float animatedValue = Mathf.Lerp(startValue, targetValue, t);
            levelBar.value = animatedValue;
            yield return null;
        }

        levelBar.value = targetValue;
    }


    // Create XP text Animation
    private IEnumerator AnimateTextMeshProValue(string targetValue){
        int targetIntValue = int.Parse(targetValue);
        float animationDuration = 1.0f; // You can adjust the duration of the animation

        for (float t = 0f; t < 1.0f; t += Time.deltaTime / animationDuration){
            int animatedValue = Mathf.RoundToInt(Mathf.Lerp(0, targetIntValue, t));
            XP_show.text = animatedValue.ToString();
            yield return null;
        }

        XP_show.text = targetValue;

        // The rest of your original code
        int intValue = targetIntValue;

        int[] levelRanges = { /* your level ranges here */ };

        for (int i = 0; i < levelRanges.Length; i++){
            // Your existing level calculation logic here
        }

        level_value.text = current_level.ToString();
    }


    // Animates changing Level value 
    private IEnumerator Animate_LevelValue(string targetValue){
        int targetIntValue = int.Parse(targetValue);
        float animationDuration = 1.0f; // You can adjust the duration of the animation

        for (float t = 0f; t < 1.0f; t += Time.deltaTime / animationDuration){
            int animatedValue = Mathf.RoundToInt(Mathf.Lerp(0, targetIntValue, t));
            level_value.text = animatedValue.ToString();
            yield return null;
        }

        level_value.text = targetValue;

    }


    // ** PLAYERPREFS used in this script
    //Saves PlayerData to PlayerPrefs.
    private void SavePlayerData(PlayerData data){
        string jsonData = JsonUtility.ToJson(data);
        PlayerPrefs.SetString(player_RewardsData, jsonData); // Details stored as "PlayerData"
        PlayerPrefs.Save();
    }

    //Load player data from PlayerPrefs
    PlayerData LoadPlayerData(){
        string jsonData = PlayerPrefs.GetString(player_RewardsData, "{}"); // Details were stored as "PlayerData"
        return JsonUtility.FromJson<PlayerData>(jsonData);
    }

}
