using System;
using System.Linq;
using UniRx;
using UnityEngine;

public class CustomerFlow : MonoBehaviour
{
    private IObservable<bool> customerObservable;
    private IObservable<bool> walkerObservable;
    private IObservable<bool> adWalkerObservable;
    private readonly Subject<IObservable<Unit>> adStartObservable = new Subject<IObservable<Unit>>();
    private IObservable<bool> tastingCustomerObservable;
    private static readonly float checkHeartInterval = 1f;
    // 歩行者の出現間隔
    private static readonly float walkerInterval = 60f / 6;
    // 試食で来るお客さん間隔
    private static readonly float tastingCustomerInterval = 5f;

    public IObservable<bool> Flow => walkerObservable.Merge(customerObservable, adWalkerObservable, tastingCustomerObservable);
    
    private void Awake()
    {
        adStartObservable.AddTo(this);
        
        var shopLevelList = SpreadsheetDataManager.Instance.GetBaseDataList<ShopLevelData>(Const.ShopLevelDataSheet);
        shopLevelList = shopLevelList.Where(data => data.shopLevel != Const.SpecialShopLevel).ToList();
        // 10分間期待値を来客の間隔に変換
        var intervalList = shopLevelList.Select(shopLevel => (heart: shopLevel.heart, interval: 60f * 10 / shopLevel.customer));
        
        // １秒間隔でハートを確認
        var changeCustomerFlowObservable = Observable.Interval(TimeSpan.FromSeconds(checkHeartInterval))
            .Select(_ => GameDataManager.GameData.Heart)
            .DistinctUntilChanged()
            .Select(heart => intervalList.Last(x => x.heart <= heart).interval);
        
        // お客さん出現タイマー
        customerObservable = changeCustomerFlowObservable
            .DistinctUntilChanged()
            // .Do(x => Debug.Log($"changeInterval:{x}"))
            .Select(customerInterval => Observable.Interval(TimeSpan.FromSeconds(customerInterval)))
            .Switch()
            // .Do(_ => Debug.Log($"customer:{GetHashCode()}"))
            .Select(_ => true);

        // 歩行者出現頻度、立ち止まり確率も設定(歩行者タイマー1分間に6人
        walkerObservable = Observable.Interval(TimeSpan.FromSeconds(walkerInterval))
            // .Do(l => Debug.Log($"walker:{GetHashCode()}"))
            .Select(x => false);

        // 宣伝時、タップすると60秒だけ稼働するストリーム
        adWalkerObservable = adStartObservable
            .Switch()
            // .Do(_ => Debug.Log($"adWalker:{GetHashCode()}"))
            .Select(_ => false);
#if DEVELOPMENT_BUILD || UNITY_EDITOR
        if (UsayaStorageManager.LoadOrDefault(UsayaStorageFilename.Settings_Data, "DebugManyWalker", false))
        {
            // Observable.Timer(TimeSpan.FromSeconds(1f), TimeSpan.FromSeconds(70f)).Subscribe(_ => { adStartObservable.OnNext(default); }).AddTo(this);
        }
#endif
        // 試食
        var tastingTimer = Observable.Interval(TimeSpan.FromSeconds(tastingCustomerInterval))
            .Where(_ => GameDataManager.GameData.TastingCount > 0)
            .Publish()
            .RefCount();
        // 試食残りカウントを減らす
        tastingTimer.Subscribe(_ =>
        {
            GameDataManager.GameData.TastingCount--;
        });
        tastingCustomerObservable = tastingTimer
            // .Do(_ => Debug.Log($"tastingCustomer remain:{GameDataManager.GameData.TastingCount}"))
            .Select(_ => true);
    }

    public void StartAdWalker(Action onComplete = null)
    {
        var timerObservable = AdWalkerTimer().Publish().RefCount();
        adStartObservable.OnNext(timerObservable);
        timerObservable.Subscribe(_ => { }, () =>
        {
            onComplete?.Invoke();
        }).AddTo(this);
    }

    private IObservable<Unit> AdWalkerTimer()
    {
        return Observable.Interval(TimeSpan.FromSeconds(3f))
            .Take(TimeSpan.FromSeconds(60f))
            .AsUnitObservable();
    }
}
