using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UniRx;
using UniRx.Triggers;
using UnityEngine;
using UnityEngine.UI;
using Random = UnityEngine.Random;

public enum CornFieldRank
{
    Rank1,
    Rank2,
    Rank3
}

public class CornField : MonoBehaviour
{
    [SerializeField] private Button promoteGrowthButton;
    [SerializeField] private GameObject harvestPrefab;
    [SerializeField] private Transform harvestInsertPosition;
    [SerializeField] private CornHarvester cornHarvester;
    [Space]
    [SerializeField] private List<PlantLine> plantLines = new List<PlantLine>();
    private readonly List<PlantLine> availableLines = new List<PlantLine>();
    private static readonly int maxPeriod = 60;
    private static readonly int minPeriod = 45;
    private static readonly int harvestedFrameInterval = 3;
    private static readonly float harvestedDistance = .6f;
    
    private readonly CompositeDisposable compositeDisposable = new CompositeDisposable();
    // Start is called before the first frame update
    void Start()
    {
        compositeDisposable.AddTo(this);
        this.UpdateAsObservable()
            .Where(_ => Input.GetKeyDown(KeyCode.R))
            .Take(1)
            .Subscribe(_ => TransitionManager.Instance.LoadScene(GameScenes.CornField)).AddTo(this);
        
        // データ
        var gameData = GameDataManager.GameData;
        CoinManager.Instance.ChangeCoin(gameData.coin);
        SetData();

        // 畑リセット
        foreach (var line in plantLines)
        {
            line.gameObject.SetActive(false);
        }
        
        // セーブデータから畑を復元
        availableLines.Clear();
        foreach (var line in gameData.PlantLines)
        {
            var plantLine = plantLines.First(x => x.LineName == line.Type);
            plantLine.gameObject.SetActive(true);
            plantLine.SetFieldLevel(line.Level);
            availableLines.Add(plantLine);
            // コーン株の進行度初回データ作成
            if (!gameData.SeedlingDataList.Exists(x => x.type == line.Type))
            {
                gameData.SeedlingDataList.Add(GenerateSeedlingData(line.Type, line.Level));
            }
        }
        GameDataManager.SaveGameData();

        // 株設定
        foreach (var line in availableLines)
        {
            var seedlingDataIndex = gameData.SeedlingDataList.FindIndex(x => x.type == line.LineName);
            var lineData = gameData.SeedlingDataList[seedlingDataIndex];
            var i = 0;
            foreach (var seedling in line.Seedlings)
            {
                var index = i;
                i++;
                seedling.SetSeedlingGene(lineData.Seedlings[index].FirstTime, lineData.Seedlings[index].Period, lineData.Seedlings[index].Level);
#if DEVELOPMENT_BUILD || UNITY_EDITOR
                if (UsayaStorageManager.LoadOrDefault(UsayaStorageFilename.Settings_Data, "DebugFastGrowing", false))
                {
                    seedling.SetSeedlingGene(lineData.Seedlings[index].FirstTime, lineData.Seedlings[index].Period / 3, lineData.Seedlings[index].Level);
                }
#endif
                seedling.Harvested.Subscribe(_ =>
                {
                    // 収穫
                    VibrationManager.Instance.PlayVibrationOnce();
                    var harvestCount = GetHarvestCount(lineData.Seedlings[index].Level);
                    var harvestedCorn = GetHarvestedCornCount(gameData.MachineLevel);
                    gameData.cornSeed += harvestedCorn * harvestCount;
                    var seedlingTransform = seedling.transform;
                    for (int j = 0; j < harvestCount; j++)
                    {
                        var pos = seedlingTransform.position;
                        if (harvestCount > 1)
                        {
                            pos += Vector3.right * (j - 1) * harvestedDistance + Vector3.forward * (j - 1);
                        }
                        // 複数株
                        this.CallWaitForFrame(harvestedFrameInterval * j, () =>
                        {
                            var harvestAnimation = Instantiate(harvestPrefab, pos, Quaternion.identity, seedlingTransform);
                            this.CallWaitForSeconds(.5f, () =>
                            {
                                var beginPos = harvestAnimation.transform.position;
                                this.CallLerp(.4f, f =>
                                {
                                    harvestAnimation.transform.position = Vector3.Lerp(beginPos, harvestInsertPosition.position, f.EaseInQuadratic());
                                }, () =>
                                {
                                    cornHarvester.AddCount(harvestedCorn);
                                    Destroy(harvestAnimation);
                                });
                            });
                        });
                    }
                    // 新しい苗
                    var newGene = GenerateSeedlingGene(line.FieldLevel);
                    seedling.SetSeedlingGene(newGene.FirstTime, newGene.Period, newGene.Level);
#if DEVELOPMENT_BUILD || UNITY_EDITOR
                    if (UsayaStorageManager.LoadOrDefault(UsayaStorageFilename.Settings_Data, "DebugFastGrowing", false))
                    {
                        seedling.SetSeedlingGene(newGene.FirstTime, newGene.Period / 3, newGene.Level);
                    }
#endif
                    gameData.SeedlingDataList[seedlingDataIndex].Seedlings[index] = newGene;
                    GameDataManager.SaveGameData();
                }).AddTo(compositeDisposable);
            }
        }

        // 時短ボタン
        promoteGrowthButton.OnClickAsObservable().Subscribe(_ =>
        {
            VibrationManager.Instance.PlayVibrationOnce();
            foreach (var line in availableLines)
            {
                var seedlingDataIndex = gameData.SeedlingDataList.FindIndex(x => x.type == line.LineName);
                for (int i = 0; i < line.Seedlings.Count; i++)
                {
                    if (Random.Range(0, 2) == 0)
                    {
                        var tmpData = gameData.SeedlingDataList[seedlingDataIndex].Seedlings[i];
                        tmpData.FirstTime = tmpData.FirstTime.AddSeconds(-1);
                        line.Seedlings[i].PromoteGrowth(tmpData.FirstTime);
                        gameData.SeedlingDataList[seedlingDataIndex].Seedlings[i] = tmpData;
                    }
                }
            }
            // 設定のセーブ
            GameDataManager.SaveGameData();
        }).AddTo(compositeDisposable);
    }

    private void SetData()
    {
        var gameData = GameDataManager.GameData;
        // 解放済みの畑
        if (gameData.PlantLines == null || gameData.PlantLines.Count == 0)
        {
            gameData.PlantLines = new List<PlantLineData>
            {
                new PlantLineData(PlantLineType.Center, CornFieldRank.Rank1),
            };
        }
        if (gameData.SeedlingDataList == null || gameData.SeedlingDataList.Count == 0)
        {
            gameData.SeedlingDataList = new List<SeedlingProgressData>();
        }
        // 収穫機レベル
        Debug.Log($"machineLevel {gameData.MachineLevel}");
        GameDataManager.SaveGameData();
    }

    private SeedlingProgressData GenerateSeedlingData(PlantLineType type, CornFieldRank level)
    {
        switch (type)
        {
            case PlantLineType.Top:
                return new SeedlingProgressData
                {
                    type = PlantLineType.Top,
                    Seedlings = new List<SeedlingData>()
                    {
                        GenerateSeedlingGene(level),
                        GenerateSeedlingGene(level),
                        GenerateSeedlingGene(level),
                        GenerateSeedlingGene(level),
                    }
                };
            case PlantLineType.Center:
                return new SeedlingProgressData
                {
                    type = PlantLineType.Center,
                    Seedlings = new List<SeedlingData>()
                    {
                        GenerateSeedlingGene(level),
                        GenerateSeedlingGene(level),
                        GenerateSeedlingGene(level),
                    }
                };
            case PlantLineType.Bottom:
                return new SeedlingProgressData
                {
                    type = PlantLineType.Bottom,
                    Seedlings = new List<SeedlingData>()
                    {
                        GenerateSeedlingGene(level),
                        GenerateSeedlingGene(level),
                        GenerateSeedlingGene(level),
                        GenerateSeedlingGene(level),
                    }
                };
            default:
                throw new ArgumentOutOfRangeException(nameof(type), type, null);
        }
    }

    private SeedlingData GenerateSeedlingGene(CornFieldRank level)
    {
        return new SeedlingData(DateTime.Now, Random.Range(minPeriod, maxPeriod + 1), level);
    }

    private int GetHarvestCount(CornFieldRank rank)
    {
        switch (rank)
        {
            case CornFieldRank.Rank1:
                return 1;
            case CornFieldRank.Rank2:
                return 2;
            case CornFieldRank.Rank3:
                return 3;
            default:
                throw new ArgumentOutOfRangeException(nameof(rank), rank, null);
        }
    }

    private int GetHarvestedCornCount(int level)
    {
        switch (level)
        {
            case 1:
                return 20;
            case 2:
                return 25;
            case 3:
                return 30;
            case 4:
                return 35;
            case 5:
                return 40;
            case 6:
                return 45;
            default:
                throw new ArgumentOutOfRangeException(nameof(level), level, null);
        }
    }
}
