using MS;
using System;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
[Serializable]
public class CellList
{
    public List<Cell> _cellPrefab;
}
public class GamePlayManager : MonoBehaviour
{
    public List<Cell> _cellPrefab;
    public List<CellList> _cellPrefab2;
    public Popup menuPopup;

    [Header("GameOver Setting")]
    public Popup gameOverPopup;
    public Popup rankedUpPopup;

    public TMP_Text starLevel;
    public TMP_Text nextStarLevel;
    public TMP_Text LevelCompleteText;
    public TMP_Text RankedUpText;

    public ParticleSystem confettiParticle;
    public Button nextBtn;
    public Button closeBtn;
    public Image fillBar;

    [Header("Layout Setting")]
    public RectTransform _levelContainer;

    public float _space;

    public LevelGroup[] levelGroups;

    public static GamePlayManager instance;

    [HideInInspector]
    public List<Cell> allCellList;

    [HideInInspector]
    public List<Cell> startCellList;

    [HideInInspector]
    public List<Cell> midCellList;

    [HideInInspector]
    public List<Cell> endCellList;

    [HideInInspector]
    public List<Cell> visibleCellList;

    [HideInInspector]
    public bool isGameOver;

    [HideInInspector]
    public bool closeGameOver;

    [HideInInspector]
    public int row;

    [HideInInspector]
    public int column;

    private List<UndoAction> undoList;

    private float startTime;

    private RectTransform rootCanvas;

    private float _levelContainerMaxHeight;

    private Vector3 _levelContainerPosition;

    private bool isRotating;


    [SerializeField] private TimerManager TimerManager;
    // Adding the isTimerLevel flag
    public static bool isTimerLevel;

    private void Awake()
    {
        instance = this;
    }

    private void Start()
    {
        rootCanvas = base.transform.parent.GetComponent<RectTransform>();
        _levelContainerMaxHeight = _levelContainer.rect.height;
        _levelContainerPosition = _levelContainer.localPosition;
        SetupLevel();
    }

    private void ShowMessagePopup()
    {
        int messagePopupIndex = GameManager.currentLevel.messagePopupIndex;
        if (messagePopupIndex != -1)
        {
            MessagePopup.instance.ShowMessage(messagePopupIndex);
        }
    }

    public void SetupLevel()
    {
        isGameOver = false;
        closeGameOver = false;
        MessagePopup.instance.HideAll();
        GameManager.currentLevelGroup = (GameManager.currentLevelGroup ?? levelGroups[GameManager.CurrentLevelGroupIndex]);
        GameManager.CurrentLevelGroupIndex = Array.IndexOf(levelGroups, GameManager.currentLevelGroup);
        GameManager.currentLevel = Resources.Load<Level>(GameManager.currentLevelGroup.ResourcesFolderPath + GameManager.CurrentLevelNo);
        if (GameManager.currentLevel == null)
        {
            UnityEngine.Debug.LogError("Level Not Found at : " + GameManager.currentLevelGroup.ResourcesFolderPath + GameManager.CurrentLevelNo);
            return;
        }
        row = GameManager.currentLevel.row;
        column = GameManager.currentLevel.column;
        float maxCellSize = GameManager.currentLevel.maxCellSize;
        startTime = Time.time;
        undoList = new List<UndoAction>();
        _levelContainer.sizeDelta = new Vector2(rootCanvas.rect.width, _levelContainerMaxHeight);
        float a = Mathf.Min(_levelContainer.rect.width / (float)column, _levelContainer.rect.height / (float)row);
        a = Mathf.Min(a, maxCellSize);
        _levelContainer.sizeDelta = new Vector2((float)column * a, (float)row * a);
        _levelContainer.transform.localPosition = _levelContainerPosition + GameManager.currentLevel.levelContainerDelta * a;
        for (int num = _levelContainer.childCount - 1; num >= 0; num--)
        {
            UnityEngine.Object.Destroy(_levelContainer.GetChild(num).gameObject);
        }
        startCellList = new List<Cell>();
        midCellList = new List<Cell>();
        endCellList = new List<Cell>();
        allCellList = new List<Cell>();
        visibleCellList = new List<Cell>();
        for (int i = 0; i < row; i++)
        {
            for (int j = 0; j < column; j++)
            {
                LevelCellData levelCellData = GameManager.currentLevel.cellList[i * column + j];
                Cell cell = Instantiate(_cellPrefab2[GameManager.PipeIndex]._cellPrefab[levelCellData.CellIndex], _levelContainer);
                //Cell cell = UnityEngine.Object.Instantiate(_cellPrefab[levelCellData.CellIndex], _levelContainer);
                cell.GetComponent<RectTransform>().sizeDelta = Vector2.one * a;
                cell.GetComponent<RectTransform>().anchoredPosition = new Vector2((float)j * a + (float)j * _space, (float)(-i) * a - (float)i * _space);
                cell.name = i + " " + j;
                cell.pos = new Vector2Int(j, i);
                cell.SetLevelData(levelCellData);
                allCellList.Add(cell);
                if (cell.pipeCellType != 0)
                {
                    if (cell.pipeCellType == CellType.Start)
                    {
                        startCellList.Add(cell);
                    }
                    else if (cell.pipeCellType == CellType.Middle)
                    {
                        midCellList.Add(cell);
                    }
                    else
                    {
                        endCellList.Add(cell);
                    }
                    visibleCellList.Add(cell);
                }
            }
        }
        GameScene.instance.UpdateUI();
        Timer.Schedule(this, 0.5f, ShowMessagePopup);
        RecursivePipeColors();
        visibleCellList.ForEach(delegate (Cell obj)
        {
            obj.UpdatePipeColor();
        });
        CheckGameOver();
    }

    public void OnButtonClick(Cell c)
    {
        if (!isRotating && !isGameOver)
        {
            undoList.Add(new UndoAction(c, c.RotationValue));
            c.RotationValue++;
            StartCoroutine(RotatePipe(c));
        }
    }

    public void Undo()
    {
        if (!isRotating && undoList != null && undoList.Count != 0)
        {
            UndoAction undoAction = undoList[undoList.Count - 1];
            undoList.RemoveAt(undoList.Count - 1);
            undoAction.cell.RotationValue = undoAction.rotValue;
            StartCoroutine(RotatePipe(undoAction.cell));
        }
    }

    private IEnumerator RotatePipe(Cell c)
    {
        AchievementManager.instance.AddAchievementProgress(GameConstants.Ach_RotatedPipes, 1);
        isRotating = true;
        if (c != null)
        {
            c.ApplyRotationOnImage(0.1f);
        }
        RecursivePipeColors();
        yield return new WaitForSeconds(0.1f);
        visibleCellList.ForEach(delegate (Cell obj)
        {
            obj.UpdatePipeColor();
        });
        isRotating = false;
        CheckGameOver();
    }

    private void RecursivePipeColors()
    {
        visibleCellList.ForEach(delegate (Cell obj)
        {
            obj.RemoveAllPipeColor();
        });
        startCellList.ForEach(delegate (Cell cell)
        {
            if (cell.pipeCellType == CellType.Start)
            {
                Cell cell2 = cell.pipes[0].T ? cell.TopCell : (cell.pipes[0].B ? cell.BottomCell : ((!cell.pipes[0].L) ? cell.RightCell : cell.LeftCell));
                Side sourceSide = cell.pipes[0].T ? Side.T : (cell.pipes[0].R ? Side.R : (cell.pipes[0].B ? Side.B : Side.L));
                if (cell2 != null)
                {
                    if (sourceSide == Side.L)
                    {
                        cell.pipes[0].LeftLeak = true;
                        cell.pipes[0].Img_1.gameObject.SetActive(true);

                        if (cell2.pipes[0].R)
                        {
                            cell.pipes[0].LeftLeak = false;
                            cell.pipes[0].Img_1.gameObject.SetActive(false);
                        }
                        if (cell2.pipes.Count > 1 && cell2.pipes[1].R)
                        {
                            cell.pipes[0].LeftLeak = false;
                            cell.pipes[0].Img_1.gameObject.SetActive(false);
                        }
                    }
                    else if (sourceSide == Side.B)
                    {
                        cell.pipes[0].BottomLeak = true;
                        cell.pipes[0].Img_1.gameObject.SetActive(true);

                        if (cell2.pipes[0].T)
                        {
                            cell.pipes[0].BottomLeak = false;
                            cell.pipes[0].Img_1.gameObject.SetActive(false);
                        }
                        if (cell2.pipes.Count > 1 && cell2.pipes[1].T)
                        {
                            cell.pipes[0].BottomLeak = false;
                            cell.pipes[0].Img_1.gameObject.SetActive(false);
                        }
                    }
                    else if (sourceSide == Side.T)
                    {
                        cell.pipes[0].TopLeak = true;
                        cell.pipes[0].Img_1.gameObject.SetActive(true);

                        if (cell2.pipes[0].B)
                        {
                            cell.pipes[0].TopLeak = false;
                            cell.pipes[0].Img_1.gameObject.SetActive(false);
                        }
                        if (cell2.pipes.Count > 1 && cell2.pipes[1].B)
                        {
                            cell.pipes[0].TopLeak = false;
                            cell.pipes[0].Img_1.gameObject.SetActive(false);
                        }
                    }
                    else if (sourceSide == Side.R)
                    {
                        cell.pipes[0].RightLeak = true;
                        cell.pipes[0].Img_1.gameObject.SetActive(true);

                        if (cell2.pipes[0].L)
                        {
                            cell.pipes[0].RightLeak = false;
                            cell.pipes[0].Img_1.gameObject.SetActive(false);
                        }
                        if (cell2.pipes.Count > 1 && cell2.pipes[1].L)
                        {
                            cell.pipes[0].RightLeak = false;
                            cell.pipes[0].Img_1.gameObject.SetActive(false);
                        }
                    }

                    cell2.FillColor(new List<PipeColor> { cell.defaultColor }, cell, sourceSide);
                }
                else
                {
                    cell.pipes[0].Img_1.gameObject.SetActive(true);
                }
            }
        });
    }

    public void GiveHint()
    {
        for (int i = 0; i < GameManager.currentLevelGroup.NoOfHint; i++)
        {
            List<Cell> list = visibleCellList.FindAll((Cell obj) => !obj.IsHint && !obj.redundant && !obj.IsInRighRotation());
            if (list != null && list.Count > 0)
            {
                list[UnityEngine.Random.Range(0, list.Count)].IsHint = true;
            }
        }
        StartCoroutine(RotatePipe(null));
    }

    private void CheckGameOver()
    {
        isGameOver = IsGameOver();
        if (isGameOver)
        {
            List<Cell> list = midCellList.FindAll((Cell x) => !x.HasAnyColor());
            foreach (Cell item in list)
            {
                item.transform.SetSiblingIndex(base.transform.childCount - 1);
                Rigidbody2D rigidbody2D = item.gameObject.AddComponent<Rigidbody2D>();
                rigidbody2D.gravityScale = 1.2f;
                rigidbody2D.AddForce(Quaternion.Euler(0f, 0f, UnityEngine.Random.Range(-30, 30)) * Vector3.up * 300f);
            }
            bool flag = list.Count > 0;
            float num = 0.7f;
            if (flag)
            {
                num += 0.6f;
            }
            Compliment.Type complimentType = GameManager.currentLevel.complimentType;
            if (complimentType != 0)
            {
                num += 0.6f;
                Compliment.instance.Show(complimentType);
            }
            StartCoroutine(ShowingGameOver(num));
        }
    }

    public bool IsGameOver()
    {
        foreach (Cell endCell in endCellList)
        {
            if (endCell.defaultColor != ColorManager.MixPipeColor(endCell.pipes[0].fillColor))
            {
                return false;
            }
        }
        foreach (Cell visibleCell in visibleCellList)
        {
            foreach (Pipe pipe in visibleCell.pipes)
            {
                if (((visibleCell.pipeCellType != CellType.Start && visibleCell.pipeCellType != CellType.End) ? ColorManager.MixPipeColor(pipe.fillColor) : visibleCell.defaultColor) != 0)
                {
                    if ((pipe.L && visibleCell.LeftCell == null) || (pipe.R && visibleCell.RightCell == null) || (pipe.T && visibleCell.TopCell == null) || (pipe.B && visibleCell.BottomCell == null))
                    {
                        return false;
                    }
                    if ((pipe.L && !visibleCell.LeftCell.HasSide(Side.R)) || (pipe.R && !visibleCell.RightCell.HasSide(Side.L)) || (pipe.T && !visibleCell.TopCell.HasSide(Side.B)) || (pipe.B && !visibleCell.BottomCell.HasSide(Side.T)))
                    {
                        return false;
                    }
                }
            }
        }
        return true;
    }

    private IEnumerator ShowingGameOver(float delay)
    {
        MessagePopup.instance.HideAll();
        PlayFabManager.Instance.playFabLeaderboards.UpdateLevelsCompleted(GameManager.CurrentLevelNo * (GameManager.CurrentLevelGroupIndex + 1));
        if (isTimerLevel)
        {
            TimerManager.StopTimer();
            double timeInSeconds = TimerManager._initialTime.TotalSeconds - TimerManager._remainingTime.TotalSeconds;
            int timeToSend = (int)(timeInSeconds * 1000);
            PlayFabManager.Instance.playFabLeaderboards.UpdateLevelCompletionTime(
                (GameManager.CurrentLevelGroupIndex + 1).ToString(), GameManager.CurrentLevelNo, timeToSend);
        }
        UpdateAchievements();
        yield return new WaitForSeconds(delay);
        LevelCompleteText.text = "Level " + GameManager.CurrentLevelNo + " Completed!";
        starLevel.text = GameManager.StarLevel + string.Empty;
        nextStarLevel.text = (GameManager.StarLevel + 1).ToString();
        fillBar.fillAmount = GameManager.StarLevelProgress;
        nextBtn.onClick.RemoveAllListeners();
        if (GameManager.currentLevelGroup.TotalLevel > GameManager.CurrentLevelNo)
        {
            nextBtn.onClick.AddListener(delegate
            {
                gameOverPopup.Close();
                Sound.instance.PlayButton();
                GameManager.CurrentLevelNo++;
                SetupLevel();
            });
            nextBtn.GetComponentInChildren<TMP_Text>().text = "NEXT";
        }
        else
        {
            nextBtn.onClick.AddListener(delegate
            {
                gameOverPopup.Close();
                closeGameOver = true;
                GameScene.instance.OnBackBtn();
            });
            nextBtn.GetComponentInChildren<TMP_Text>().text = "BACK";
        }
        nextBtn.interactable = false;
        gameOverPopup.Open();
        confettiParticle.Play();
        yield return new WaitForSeconds(0.5f);
        if (!isTimerLevel)
        {
            if (GameManager.currentLevelGroup.CompletedLevel < GameManager.CurrentLevelNo)
            {
                int sl = GameManager.StarLevel;
                for (int i = 0; i < GameManager.currentLevelGroup.StarXPReward; i++)
                {
                    GameManager.AddStar(1);
                    starLevel.text = GameManager.StarLevel + string.Empty;
                    nextStarLevel.text = (GameManager.StarLevel + 1).ToString();
                    if (fillBar.fillAmount > GameManager.StarLevelProgress)
                    {
                        while (fillBar.fillAmount < 1f)
                        {
                            fillBar.fillAmount += 0.01f;
                            yield return new WaitForSeconds(0.01f);
                        }
                        fillBar.fillAmount = 0f;
                    }
                    while (fillBar.fillAmount < GameManager.StarLevelProgress)
                    {
                        fillBar.fillAmount += 0.01f;
                        yield return new WaitForSeconds(0.01f);
                    }
                }
                if (sl < GameManager.StarLevel)
                {
                    RankedUpText.text = GameManager.StarLevel.ToString();
                    ShowRankedUpScreen();
                    confettiParticle.Play();
                    GameManager.Coin += UnityEngine.Random.Range(30, 45);
                    GameScene.instance.UpdateUI();
                }
            }
        }
        nextBtn.interactable = true;
        GameManager.currentLevelGroup.SetLevelCompleted(GameManager.CurrentLevelNo, Time.time - startTime);
        if (AdmobController.isInterAdAvailable)
            IronSource.Agent.showInterstitial();
    }

    private void UpdateAchievements()
    {
        switch (GameManager.CurrentLevelGroupIndex)
        {
            case 0:
                AchievementManager.instance.AddAchievementProgress(GameConstants.Ach_CompleteEasyLevelKey, 1);
                break;
            case 1:
                AchievementManager.instance.AddAchievementProgress(GameConstants.Ach_CompleteMediumLevelKey, 1);
                break;
            case 2:
                AchievementManager.instance.AddAchievementProgress(GameConstants.Ach_CompleteHardLevelKey, 1);
                break;
            case 3:
                AchievementManager.instance.AddAchievementProgress(GameConstants.Ach_CompleteAdvanceLevelKey, 1);
                break;
            case 4:
                AchievementManager.instance.AddAchievementProgress(GameConstants.Ach_CompleteExpertLevelKey, 1);
                break;
        }
    }

    private void ShowRankedUpScreen()
    {
        rankedUpPopup.Open();
    }

    public void OnRankedUpContinue()
    {
        rankedUpPopup.Close();
    }

    public void NextGame()
    {
        if (!isTimerLevel)
        {
            if (GameManager.CurrentLevelNo > GameManager.currentLevelGroup.CompletedLevel)
            {
                if (GameManager.Coin < GameConfig.instance.numCoinForSkipGame)
                {
                    Toast.instance.ShowMessage("You don't have enough coins");
                    return;
                }
                GameManager.Coin -= GameConfig.instance.numCoinForSkipGame;
                GameManager.currentLevelGroup.SetLevelCompleted(GameManager.CurrentLevelNo, Time.time - startTime);
            }
        }
        else
        {
            if (GameManager.CurrentLevelNo > GameManager.currentLevelGroup.CompletedLevel_Timer)
            {
                if (GameManager.Coin < GameConfig.instance.numCoinForSkipGame)
                {
                    Toast.instance.ShowMessage("You don't have enough coins");
                    return;
                }
                GameManager.Coin -= GameConfig.instance.numCoinForSkipGame;
                GameManager.currentLevelGroup.SetLevelCompleted(GameManager.CurrentLevelNo, Time.time - startTime);
            }
        }
        menuPopup.Close();
        Sound.instance.PlayButton();
        if (GameManager.currentLevelGroup.TotalLevel > GameManager.CurrentLevelNo)
        {
            Timer.Schedule(this, 0.8f, delegate
            {
                GameManager.CurrentLevelNo++;
                SetupLevel();
            });
        }
        else
        {
            GameScene.instance.OnBackBtn();
        }
    }
}