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

public class Shopping : MonoBehaviour
{
    [SerializeField] private ShopListView listView;
    // Start is called before the first frame update
    private Subject<int> changeCoinSubject = new Subject<int>();
    void Start()
    {
        changeCoinSubject.AddTo(this);
        
        var gameData = GameDataManager.GameData;
        CoinManager.Instance.ChangeCoin(gameData.Coin);
        HeartMeter.Instance.Initialize();
        HeartMeter.Instance.SetHeart(gameData.Heart);
        
        // 一覧データ
        var shopDataList = SpreadsheetDataManager.Instance.GetBaseDataList<ShopData>(Const.ShopDataSheet);
        foreach (var shopData in shopDataList)
        {
            var itemView = listView.AddItemView(shopData);
            itemView.SetData(shopData);
            itemView.SetStockCount(GetItemAmount(shopData));
            // コインを監視して購入可能状態を切り替え
            changeCoinSubject.Subscribe(ownCoin =>
            {
                itemView.SetItemActive(shopData.price <= ownCoin);
            }).AddTo(this);
            var purchaseSubject = new Subject<int>();
            purchaseSubject.AddTo(itemView);
            purchaseSubject.Subscribe(amount =>
            {
                // アイテムを増やす
                AddItem(shopData, amount);
                itemView.SetStockCount(GetItemAmount(shopData));
                CoinManager.Instance.SubCoin(shopData.price * amount);
                gameData.Coin = CoinManager.Instance.OwnCoin;
                changeCoinSubject.OnNext(gameData.Coin);
                GameDataManager.SaveGameData();
            }).AddTo(itemView);
            // アイテム購入クリック購読
            itemView.PurchaseButtonObservable
                .Where(_ => shopData.price <= CoinManager.Instance.OwnCoin)
                .Subscribe(_ =>
                {
                    LocalCacheManager.Save(ShopItemPurchaseView.ItemPurchaseTag, (shopData, GetItemAmount(shopData), new Action<int>(x => purchaseSubject.OnNext(x))));
                    TransitionManager.Instance.LoadSceneAdditive(GameScenes.Purchase);
                }).AddTo(itemView);
            // show detail view
            itemView.DetailButtonObservable.Subscribe(_ =>
            {
                LocalCacheManager.Save(ShopItemDetailView.ItemDetailTag, shopData);
                TransitionManager.Instance.LoadSceneAdditive(GameScenes.ShoppingExplanation);
            }).AddTo(itemView);
        }
        changeCoinSubject.OnNext(CoinManager.Instance.OwnCoin);
    }

    private int GetItemAmount(ShopData shopData)
    {
        var gameData = GameDataManager.GameData;
        switch (shopData.Category)
        {
            case ItemCategory.Material:
                return gameData.Material.Find(data => data.Id == shopData.itemId)?.Amount ?? 0;
            case ItemCategory.Recipe:
                return gameData.MyRecipes.Contains(shopData.itemId) ? 1 : 0;
            case ItemCategory.Pan:
                return gameData.Pans.Contains(shopData.itemId) ? 1 : 0;
            default:
                throw new ArgumentOutOfRangeException();
        }
    }

    private void AddItem(ShopData shopData, int amount)
    {
        var gameData = GameDataManager.GameData;
        switch (shopData.Category)
        {
            case ItemCategory.Material:
                var index = gameData.Material.FindIndex(x => x.Id == shopData.itemId);
                if (index == -1)
                {
                    index = gameData.Material.Count;
                    gameData.Material.Add(new MaterialData
                    {
                        Id = shopData.itemId,
                        Amount = 0
                    });
                }
                gameData.Material[index].Amount += amount;
                break;
            case ItemCategory.Recipe:
                if (!gameData.MyRecipes.Contains(shopData.itemId))
                {
                    gameData.MyRecipes = new List<int>(gameData.MyRecipes){shopData.itemId}.ToArray();
                }
            break;
            case ItemCategory.Pan:
                if (!gameData.Pans.Contains(shopData.itemId))
                {
                    gameData.Pans = new List<int>(gameData.Pans){shopData.itemId}.ToArray();
                }
            break;
            default:
                throw new ArgumentOutOfRangeException();
        }
    }
}
