using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UI;

public class SpinnerMainGame : MonoBehaviour
{
    public static SpinnerMainGame instance;
    public Transform forceLevelBar_P1, forceLevelBar_P2;
    private float curForceLevel_P1, curForceLevel_P2;
    private float forceLevelStep;
    private float maxForce;
    private bool isForceLevel_P1, isForceLevel_P2;
    public GameObject player_P1, player_P2;
    public GameObject gameBase;
    private int gameTime, curTime;
    public Text gameTimeTxt, gameStatusTxt;
    public float delayTime;
    private bool isGameEnd, isGameStart;
    private int maxRound, roundNum;
    public Button startBtn;
    private int gamePt_P1,gamePt_P2;
    public GameObject gamePtTxt_P1, gamePtTxt_P2;
    private bool isOver_P1, isOver_P2;
    public GameObject battleBase;
    //private bool isInitStart;

    private void Awake()
    {
        instance = this;
    }



    // Start is called before the first frame update
    void Start()
    {
 
        LoadBase();
        StartCoroutine(LoadPlayer());
        maxForce = 600;
        forceLevelStep = maxForce; //1s for max force level        
        gameTime = 180;
        
        maxRound = 5;
        Init();
        //Debug.Log(maxRound / 2+1);
    }
    private void FixedUpdate()
    {
        //Debug.Log(Time.fixedDeltaTime);
        //Debug.Log(isForceLevel_P1 + "," + isForceLevel_P2);


        if (isGameStart)
        {


            if (isForceLevel_P1)
            {
                curForceLevel_P1 += forceLevelStep * Time.fixedDeltaTime;
                if (curForceLevel_P1 > maxForce)
                {
                    curForceLevel_P1 = 0;

                }
                UpdateForceBar(curForceLevel_P1, "P1");
            }
            if (isForceLevel_P2)
            {
                curForceLevel_P2 += forceLevelStep * Time.fixedDeltaTime;
                if (curForceLevel_P2 > maxForce)
                {
                    curForceLevel_P2 = 0;
                }
                UpdateForceBar(curForceLevel_P2, "P2");
            }
            delayTime += Time.fixedDeltaTime;
            //Debug.Log(delayTime);
            if (delayTime >= 1 && !isGameEnd)
            {
                delayTime = 0;
                curTime -= 1;
                UpdateGameTime(curTime);
                if (curTime == 120)
                {
                    StartCoroutine(RemoveBaseRing("Ring4_"));
                    StartCoroutine(AddCupboard("Ring3_"));
                }
                else if (curTime == 60)
                {
                    StartCoroutine(RemoveBaseRing("Ring3_"));
                    StartCoroutine(AddCupboard("Ring2_"));
                }
                else if (curTime == 30)
                {
                    StartCoroutine(RemoveBaseRing("Ring2_"));
                }


                if (curTime == 0)
                {
                    isGameEnd = true;
                }
            }
        }
    }



    // Update is called once per frame
    void Update()
    {
        
    }
    private void Init()
    {
        curForceLevel_P1 = 0;
        curForceLevel_P2 = 0;
        isForceLevel_P1 = true;
        isForceLevel_P2 = true;
        UpdateForceBar(curForceLevel_P1, "P1");
        UpdateForceBar(curForceLevel_P2, "P2");
        curTime = gameTime;
        delayTime = 0;
        UpdateGameTime(curTime);
        isGameEnd = false;
        isGameStart = false;
        gameStatusTxt.enabled = false;
        roundNum = 1;
        gamePt_P1 = 0;
        gamePt_P2 = 0;
        for (int i = 0; i < 3; i++)
        {
            ResetGamePoint(i, "P1");
            ResetGamePoint(i, "P2");
        }
        isOver_P1 = false;
        isOver_P2 = false;

    }



    void LoadBase()
    {
        GameObject obj = Instantiate<GameObject>(battleBase);
        obj.transform.position = Vector3.zero;
        obj.name = "BattleBase";


        
        for(int i = 0; i < obj.transform.childCount; i++)
        {
            obj.transform.GetChild(i).AddComponent<MeshCollider>();
            obj.transform.GetChild(i).AddComponent<Rigidbody>();
            obj.transform.GetChild(i).GetComponent<Rigidbody>().useGravity = false;
            obj.transform.GetChild(i).GetComponent<Rigidbody>().isKinematic = true;
            obj.transform.GetChild(i).tag = "Base";
            //Debug.Log(obj.transform.childCount);
            if (obj.transform.GetChild(i).childCount > 0 && i<obj.transform.childCount-23)
            {
                obj.transform.GetChild(i).GetChild(0).gameObject.SetActive(false);
            }
                

        }


    }



    IEnumerator LoadPlayer()
    {
        yield return new WaitForSeconds(1);
        int n = 20;
        float x_P1 = -5;
        float x_P2 = 5;
        float y = 0.4f;
        player_P1.transform.position = new Vector3(x_P1, y, 0);
        player_P2.transform.position = new Vector3(x_P2, y, 0);
        player_P1.transform.rotation = Quaternion.Euler(new Vector3(0, 100, 0));
        player_P2.transform.rotation = Quaternion.Euler(new Vector3(0, -100, 0));

        while (n > 0)
        {
            x_P1 += 0.1f;
            x_P2 -= 0.1f;
            player_P1.transform.position = new Vector3(x_P1, y, 0);
            player_P2.transform.position = new Vector3(x_P2, y, 0);
            
            player_P1.transform.Rotate(0,-35,0);
            player_P2.transform.Rotate(0, 35, 0);
            n--;
            yield return null;
            

        }
        player_P1.transform.GetComponent<Rigidbody>().useGravity = true;
        player_P2.transform.GetComponent<Rigidbody>().useGravity = true;
        player_P1.transform.GetComponent<Rigidbody>().isKinematic = false;
        player_P2.transform.GetComponent<Rigidbody>().isKinematic = false;

    }


    void UpdateForceBar(float f, string player)
    {
        f = f / maxForce;
        if (player == "P1")
        {
            
            forceLevelBar_P1.GetComponent<Image>().fillAmount = f;
        }
        if (player == "P2")
        {
            forceLevelBar_P2.GetComponent<Image>().fillAmount = f;
        }
    }
    public float GetForce(string player)
    {
        float f=0;
        if (player == "P1")
        {
            isForceLevel_P1 = false;
            
            f = curForceLevel_P1;
            UpdateForceBar(f,player);
            StartCoroutine(ForceLevelCoolDown(f, "P1"));

        }
        if (player == "P2")
        {
            isForceLevel_P2 = false;
            f = curForceLevel_P2;
            UpdateForceBar(f, player);
            StartCoroutine(ForceLevelCoolDown(f, "P2"));
        }

        return f;
    }
    IEnumerator ForceLevelCoolDown(float f,string player)
    {
        float fStep = f/20;
        if(player == "P1")
        {
            while (f>0)
            {
                f -= fStep;
                UpdateForceBar(f, "P1");
                yield return new WaitForSeconds(0.05f);
            }
            isForceLevel_P1 = true;
            curForceLevel_P1 = 0;
            player_P1.SendMessage("ResetAddForce", "P1");
            
        }
        if (player == "P2")
        {
            while (f > 0)
            {
                f -= fStep;
                UpdateForceBar(f, "P2");
                yield return new WaitForSeconds(0.05f);
            }
            isForceLevel_P2 = true;
            curForceLevel_P2 = 0;
            player_P2.SendMessage("ResetAddForce", "P2");
        }


    }
    void UpdateGameTime(int t)
    {
        int minutes = Mathf.FloorToInt(t/60);
        int seconds = t-(minutes*60);
        string min, sec;
        min = minutes.ToString();
        if (seconds < 10)
        {
            sec = "0"+seconds.ToString();
        }
        else
        {
            sec = seconds.ToString();
        }
        gameTimeTxt.text = "0" + min + ":" + sec;

    }

    IEnumerator RemoveBaseRing(string ring)
    {
        GameObject ringObj;
        int n=-1;
        switch (ring)
        {
            case "Ring2_":
                n = 11;
                break;
            
            case "Ring3_":
                n = 15;

                break;
            case "Ring4_":
                n = 23;
                
                break;
        }
        for (int i = n; i > -1; i--)
        {
            ringObj = GameObject.Find(ring + i);
            ringObj.GetComponent<Rigidbody>().useGravity = true;
            //Destroy(ringObj.GetComponent<MeshCollider>());
            ringObj.GetComponent<MeshCollider>().convex = true;
            ringObj.GetComponent<Rigidbody>().isKinematic = false;
            yield return new WaitForSeconds(0.1f);
        }
    }
    IEnumerator AddCupboard(string ring)
    {
        GameObject ringObj;
        int n = -1;
        switch (ring)
        {
            case "Ring2_":
                n = 11;
                break;

            case "Ring3_":
                n = 15;

                break;

        }
        for (int i = n; i > -1; i--)
        {
            ringObj = GameObject.Find(ring + i);
            if(ringObj.transform.childCount > 0)
            {
                ringObj.transform.GetChild(0).gameObject.SetActive(true);
            }
            yield return new WaitForSeconds(0.1f);
        }
        //yield return new WaitForSeconds(2);
    
    }


    public void GameStart()
    {
        isGameStart = true;
        startBtn.gameObject.SetActive(false);
        player_P1.SendMessage("GameStatus", "Start");
        player_P2.SendMessage("GameStatus", "Start");
        StartCoroutine(ShowRoundText(roundNum));

    }
    public void NextRound()
    {
        //DestroyBase();
        player_P1.transform.GetComponent<Rigidbody>().useGravity = false;
        player_P2.transform.GetComponent<Rigidbody>().useGravity = false;
        player_P1.transform.GetComponent<Rigidbody>().isKinematic = true;
        player_P2.transform.GetComponent<Rigidbody>().isKinematic = true;
        Destroy(GameObject.Find("BattleBase"));
        
        LoadBase();
        StartCoroutine(LoadPlayer());
        isOver_P1 = false;
        isOver_P2 = false;
        curTime = gameTime;
        roundNum++;
        StartCoroutine(ShowRoundText(roundNum));
        UpdateGameTime(gameTime);
        isGameStart = true;
        player_P1.SendMessage("GameStatus", "Start");
        player_P2.SendMessage("GameStatus", "Start");

    }
    IEnumerator Restart()
    {
        yield return new WaitForSeconds(3);
        player_P1.transform.GetComponent<Rigidbody>().useGravity = false;
        player_P2.transform.GetComponent<Rigidbody>().useGravity = false;
        player_P1.transform.GetComponent<Rigidbody>().isKinematic = true;
        player_P2.transform.GetComponent<Rigidbody>().isKinematic = true;
        Destroy(GameObject.Find("BattleBase"));

        LoadBase();
        StartCoroutine(LoadPlayer());
        Init();
        startBtn.gameObject.SetActive(true);
        //yield return null;
    }

    IEnumerator ShowRoundText(int n)
    {
        gameStatusTxt.text = "ROUND " + n.ToString();
        gameStatusTxt.enabled = true;
        yield return new WaitForSeconds(1);
        gameStatusTxt.enabled = false;
    }
    IEnumerator ShowGameResult(string result)
    {
        Debug.Log(result);
        gameStatusTxt.text = result;
        gameStatusTxt.enabled = true;
        yield return new WaitForSeconds(2);
        gameStatusTxt.enabled = false;
    }


    public void SetGamePoint(int idx, string player)
    {
        if (player == "P1")
        {
            gamePtTxt_P1.transform.GetChild(idx).GetChild(0).gameObject.SetActive(true);
        }
        if (player == "P2")
        {
            gamePtTxt_P2.transform.GetChild(idx).GetChild(0).gameObject.SetActive(true);
        }
    }
    public void ResetGamePoint(int idx, string player)
    {
        if (player == "P1")
        {
            gamePtTxt_P1.transform.GetChild(idx).GetChild(0).gameObject.SetActive(false);
        }
        if (player == "P2")
        {
            gamePtTxt_P2.transform.GetChild(idx).GetChild(0).gameObject.SetActive(false);
        }
    }
    public void SetPlayerLose(string player)
    {

        
        isGameStart = false;
        player_P1.SendMessage("GameStatus", "Over");
        player_P2.SendMessage("GameStatus", "Over");
        if (!isOver_P1 && !isOver_P2)
        {
            
            StartCoroutine(JudgeKO());
        }
        if (player == "P1")
        {
            isOver_P1 = true;
        }
        if (player == "P2")
        {
            isOver_P2 = true;
        }
         
    }
    
    
    IEnumerator JudgeKO()
    {
        yield return new WaitForSeconds(2);

        Debug.Log(isOver_P1 + "," + isOver_P2);
        if (isOver_P1 && isOver_P2)
        {
            StartCoroutine(ShowGameResult("DOUBLE K.O."));
        }
        else if (isOver_P1)
        {
            StartCoroutine(ShowGameResult("K.O."));
            SetGamePoint(gamePt_P2, "P2");
            gamePt_P2++;
            
        }
        else
        {
            StartCoroutine(ShowGameResult("K.O."));
            SetGamePoint(gamePt_P1, "P1");
            gamePt_P1++;
        }
        yield return new WaitForSeconds(2);
        StartCoroutine(JudgeWinner());
    }
    IEnumerator JudgeWinner()
    {
        bool isWinnerSet = false;
        if (gamePt_P1 == maxRound / 2+1)
        {
            StartCoroutine(ShowGameResult("PLAYER 1 WIN"));
            isWinnerSet = true;
        }
        if (gamePt_P2 == 3)
        {
            StartCoroutine(ShowGameResult("PLAYER 2 WIN"));
            isWinnerSet = true;
        }

        if (roundNum == maxRound)
        {
            if (gamePt_P1 == gamePt_P2)
            {
                StartCoroutine(ShowGameResult("GAME DRAW"));
            }
            if (gamePt_P1 > gamePt_P2)
            {
                StartCoroutine(ShowGameResult("PLAYER 1 WIN"));
            }
            if (gamePt_P2 > gamePt_P1)
            {
                StartCoroutine(ShowGameResult("PLAYER 2 WIN"));

            }
            isWinnerSet = true;
        }
        yield return new WaitForSeconds(2);

        if (isWinnerSet)
        {
            //yield return new WaitForSeconds(3);
            //startBtn.gameObject.SetActive(true);
            //Init();
            StartCoroutine(Restart());
        }
        else
        {
            NextRound();
        }
    }
}
