using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using MyGame.Scripts;
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);
        
        SoundManager.Instance.PlayBGM("bgm_shopping");
        var gameData = GameDataManager.GameData;
        CoinManager.Instance.ChangeCoin(gameData.Coin);
        HeartMeter.Instance.Initialize(gameData.ViewedShopLevel, gameData.Heart);
        GameDataObserver.Instance.ShopLevelUpdate
            .Where(x => x)
            .Subscribe(x =>
            {
                LocalCacheManager.Save(ShopLevelUp.DataTag, gameData.ViewedShopLevel + 1);
                TransitionManager.Instance.LoadSceneAdditive(GameScenes.StoreLevel);
            }).AddTo(this);
        
        // 一覧データ
        var shopDataList = SpreadsheetDataManager.Instance.GetBaseDataList<ShopData>(Const.ShopDataSheet);
        foreach (var shopData in shopDataList)
        {
            if (shopData.Category == ItemCategory.Special)
            {
                continue;
            }
            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
                .ThrottleFirst(TimeSpan.FromSeconds(.3f))
                .Where(_ => shopData.price <= CoinManager.Instance.OwnCoin)
                .Subscribe(_ =>
                {
                    ShopItemPurchaseView.ShowDialog((shopData, GetItemAmount(shopData)), x =>
                    {
                        purchaseSubject.OnNext(x);
                        if (gameData.isFirstPlay)
                        {
                            TutorialManager.Instance.ShowTutorialConversation(6, () =>
                            {
                                var go = FindObjectOfType<FooterManager>().transform;
                                go.transform.FindChildByName("Button_Main", t =>
                                {
                                    TutorialManager.Instance.ShowTutorialMask(go.parent, t as RectTransform, true);
                                });
                            });
                        }
                    });
                }).AddTo(itemView);
            // show detail view
            itemView.DetailButtonObservable.ThrottleFirst(TimeSpan.FromSeconds(.3f)).Subscribe(_ =>
            {
                LocalCacheManager.Save(ShopItemDetailView.ItemDetailTag, shopData);
                TransitionManager.Instance.LoadSceneAdditive(GameScenes.ShoppingExplanation);
            }).AddTo(itemView);
        }
        listView.SetTab(ItemCategory.Material);
        changeCoinSubject.OnNext(CoinManager.Instance.OwnCoin);
        
        if (gameData.isFirstPlay)
        {
            listView.ScrollRect.vertical = false;
            TutorialManager.Instance.ShowTutorialConversation(5, () =>
            {
                // マスク表示
                var view = listView.ScrollRect.content.GetChild(0).GetComponent<ShopItemView>();
                var viewRectTransform = view.transform as RectTransform;
                var go = TutorialManager.Instance.ShowTutorialMask(listView.transform.parent, viewRectTransform);
                view.PurchaseButtonObservable.Take(1).Subscribe(_ =>
                {
                    DestroyImmediate(go);
                }).AddTo(this);
            });
        }
    }

    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();
                    gameData.DailyRecipeGetCount++;
                }
            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();
        }
    }
}
