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

public class HeartMeter : SingletonMonoBehaviour<HeartMeter>
{
    [SerializeField] private Slider slider;
    [SerializeField] private TextMeshProUGUI heartLevel;

    private Coroutine coroutine;
    private List<int> levelList = new List<int>();
    private int currentHeartCount;
    private readonly ReactiveProperty<float> viewHeartCount = new ReactiveProperty<float>();
    public IReadOnlyReactiveProperty<int> ShopLevel => shopLevel;
    private readonly ReactiveProperty<int> shopLevel = new ReactiveProperty<int>();
    private CompositeDisposable compositeDisposable = new CompositeDisposable();
    
    private void Awake()
    {
        if (CheckInstance()) return;
    }

    private void Start()
    {
        shopLevel.AddTo(this);
        viewHeartCount.AddTo(this);
        compositeDisposable.AddTo(this);
    }

    public void Initialize()
    {
        levelList = SpreadsheetDataManager.Instance.GetBaseDataList<ShopLevelData>(Const.ShopLevelDataSheet).Select(shopLevelData => shopLevelData.heart).ToList();
        compositeDisposable.Clear();
        shopLevel.Subscribe(x =>
        {
            heartLevel.text = $"{x}";
        }).AddTo(compositeDisposable);
        viewHeartCount.SkipLatestValueOnSubscribe().Subscribe(heartCount =>
        {
            if (levelList.Empty())
            {
                return;
            }
            shopLevel.Value = GetShopLevel(Mathf.FloorToInt(heartCount)) + 1;
            if (levelList.Count == shopLevel.Value)
            {
                slider.value = 1;
            }
            else
            {
                slider.value = (heartCount - levelList[shopLevel.Value - 1]) / (levelList[shopLevel.Value] - levelList[shopLevel.Value - 1]);
            }
        }).AddTo(compositeDisposable);
    }
    
    public void SetHeart(int heartCount)
    {
        currentHeartCount = heartCount;
        viewHeartCount.SetValueAndForceNotify(heartCount);
    }

    private int GetShopLevel(int heartCount)
    {
        return levelList.FindLastIndex(x => x <= heartCount);
    }

    public void AddHeart(int value)
    {
        this.SafeStopCoroutine(coroutine);
        currentHeartCount += value;
        coroutine = this.CallWaitForSeconds(1f, () =>
        {
            SetHeart(currentHeartCount);
        });
        this.CallLerp(1f, f =>
        {
            viewHeartCount.Value = Mathf.Min(currentHeartCount, viewHeartCount.Value + value * Time.deltaTime);
        });
    }
}