using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class PlayerController : MonoBehaviour {

    /*Pillar Techs
     * 1 - Pillars
     * 2 - Spike-Topped Pillars
     * 3 - Mega Jump + Frequency
     * 4 - Spike-Covered Pillars
     * 5 - Platforms
     * 6 - Spiky Platforms
     * 7 - Spiky Islands
     */

    /*Patch Techs
     * 1 - Small Spiky Patches
     * 2 - Large Spiky Patches
     * 3 - Mega Speed + Frequency
     * 4 - Huge Spike Patches
     * 5 - Loose Boxes
     * 6 - Loose Spikes
     * 7 - Large Loose Spikes
     */

    public int Speed;
    public int JumpForce;
    public Rigidbody rb;
    public string[] PillarTechs;
    public string[] PatchTechs;
    public int PillarAdv;
    public int PatchAdv;
    public Material DeadMaterial;
    public Material NotDeadMaterial;
    public Renderer Renderer;
    public int DeathTime;
    public Text PillarButtonText;
    public Text PatchButtonText;
    public Text TitleText;
    public Text InfoText;
    public Button PillarButton;
    public Button PatchButton;
    public GameObject Camera;

    public GameObject Ground;
    public GameObject Pillars;
    public GameObject HardPillars;
    public GameObject HarderPillars;
    public GameObject Spikes;
    public GameObject HardSpikes;
    public GameObject HarderSpikes;
    public GameObject LevelEnd;
    public GameObject Loose;
    public GameObject HardLoose;
    public GameObject HarderLoose;
    public GameObject Platform;
    public GameObject HardPlatform;
    public GameObject HarderPlatform;
    public int Freq;
    public GameObject[] RainbowPartyCubes;

    private Quaternion Rotation;
    private float xpos;
    private bool Dead = false;
    private int DeathTimer;
    private bool WaitingForButton;
    private int DeathCount;
    private float RandXPos;
    private bool Won;
    private bool Rainbow;

    void Start()
    {
        Rotation = new Quaternion(0, 0, 0, 0);
    }

    void FixedUpdate ()
    {
        //Basic movement
        if (PatchAdv >= 3 && !Dead)
        {
            rb.AddForce(Input.GetAxis("Horizontal") * Speed * 2, 0, 0);
        }
        else
        {
            rb.AddForce(Input.GetAxis("Horizontal") * Speed, 0, 0);
        }

        //Vertical looping
        if (rb.position.y <= -10)
        {
            rb.MovePosition(new Vector3(rb.position.x, 15, rb.position.z));
        }

        //Off the left edge
        if (rb.position.x <= -20)
        {
            rb.MovePosition(new Vector3(-17, rb.position.y, 0));
        }

        //Off the right edge
        if (rb.position.x >= xpos + 43)
        {
            rb.MovePosition(new Vector3(xpos + 43, rb.position.y, 0));
            rb.velocity = new Vector3(0, rb.velocity.y, 0);
        }
        else if (rb.position.x >= xpos + 3 && WaitingForButton)
        {
            rb.MovePosition(new Vector3(xpos + 3, rb.position.y, 0));
            rb.velocity = new Vector3(0, rb.velocity.y, 0);
        }

        //Mega jump
        if (PillarAdv >= 3)
        {
            if (Input.GetButton("Jump1") || Input.GetButton("Jump2"))
            {
                rb.AddForce(new Vector3(0, JumpForce / 1.5f, 0));
            }
        }

        //Death timer
        if (Dead)
        {
            DeathTimer++;
        }

        //Respawn
        if (DeathTimer >= DeathTime)
        {
            DeathTimer = 0;
            DeathCount++;
            Dead = false;
            rb.gameObject.layer = 10;
            Renderer.material = NotDeadMaterial;
            Instantiate(Loose, rb.position, rb.rotation);
            rb.constraints = RigidbodyConstraints.FreezeRotation | RigidbodyConstraints.FreezePositionZ;
            rb.MovePosition(new Vector3(xpos, 3, 0));
            rb.rotation = Quaternion.Euler(0, 0, 0);
            rb.velocity = new Vector3(0, 0, 0);
        }

        //Camera
        Camera.transform.position = new Vector3(rb.position.x, 9, -7);

        //Quitting
        if (Input.GetButton("Quit"))
        {
            SceneManager.LoadScene("menu");
        }
    }

    void Generate()
    {
        //level generation

        Instantiate(Ground, new Vector3(xpos + 20, -1, 0), Rotation);
        Instantiate(LevelEnd, new Vector3(xpos + 40, -0.5f, 0), Rotation);

        if (!Won || Rainbow)
        {
            //Pillars
            if (PillarAdv >= 1 && PillarAdv < 4)
            {
                for (int i = 0; i < Random.Range(Freq, Freq + 2); i++)
                {
                    RandXPos = xpos + Random.Range(5.5f, 34.5f);

                    Instantiate(Pillars, new Vector3(RandXPos, 1, 0), Rotation);
                }
            }
            if (PillarAdv >= 2)
            {
                for (int i = 0; i < Random.Range(Freq, Freq + 2); i++)
                {
                    RandXPos = xpos + Random.Range(5.5f, 34.5f);

                    Instantiate(HardPillars, new Vector3(RandXPos, 1, 0), Rotation);
                }
            }
            if (PillarAdv >= 4)
            {
                for (int i = 0; i < Random.Range(Freq, Freq + 2); i++)
                {
                    RandXPos = xpos + Random.Range(5.5f, 34.5f);

                    Instantiate(HarderPillars, new Vector3(RandXPos, 1, 0), Rotation);
                }
            }

            //Spike Patches
            if (PatchAdv >= 1)
            {
                for (int i = 0; i < Random.Range(Freq, Freq + 2); i++)
                {
                    RandXPos = xpos + Random.Range(6.5f, 33.5f);

                    Instantiate(Spikes, new Vector3(RandXPos, 0.5f, 0), Rotation);
                }
            }
            if (PatchAdv >= 2)
            {
                for (int i = 0; i < Random.Range(Freq, Freq + 2); i++)
                {
                    RandXPos = xpos + Random.Range(7.5f, 32.5f);

                    Instantiate(HardSpikes, new Vector3(RandXPos, 1, 0), Rotation);
                }
            }
            if (PatchAdv >= 4)
            {
                for (int i = 0; i < Random.Range(Freq, Freq + 2); i++)
                {
                    RandXPos = xpos + Random.Range(8.5f, 31.5f);

                    Instantiate(HarderSpikes, new Vector3(RandXPos, 2, 0), Rotation);
                }
            }

            //Loose Objects
            if (PillarAdv >= 5 && PatchAdv < 7)
            {
                for (int i = 0; i < Random.Range(Freq, Freq + 2); i++)
                {
                    RandXPos = xpos + Random.Range(5.5f, 34.5f);

                    Instantiate(Loose, new Vector3(RandXPos, Random.Range(1, 10), 0), Rotation);
                }
            }
            if (PillarAdv >= 6)
            {
                for (int i = 0; i < Random.Range(Freq, Freq + 2); i++)
                {
                    RandXPos = xpos + Random.Range(5.5f, 34.5f);

                    Instantiate(HardLoose, new Vector3(RandXPos, Random.Range(1, 10), 0), Rotation);
                }
            }
            if (PillarAdv >= 7)
            {
                for (int i = 0; i < Random.Range(Freq, Freq + 2); i++)
                {
                    RandXPos = xpos + Random.Range(5.5f, 34.5f);

                    Instantiate(HarderLoose, new Vector3(RandXPos, Random.Range(1, 10), 0), Rotation);
                }
            }

            //Platforms
            if (PatchAdv >= 5)
            {
                for (int i = 0; i < Random.Range(Freq, Freq + 2); i++)
                {
                    RandXPos = xpos + Random.Range(5.5f, 34.5f);

                    Instantiate(Platform, new Vector3(RandXPos, Random.Range(10, 12), 0), Rotation);
                }
            }
            if (PatchAdv >= 6)
            {
                for (int i = 0; i < Random.Range(Freq, Freq + 2); i++)
                {
                    RandXPos = xpos + Random.Range(5.5f, 34.5f);

                    Instantiate(HardPlatform, new Vector3(RandXPos, Random.Range(10, 12), 0), Rotation);
                }
            }
            if (PatchAdv >= 7)
            {
                for (int i = 0; i < Random.Range(Freq, Freq + 2); i++)
                {
                    RandXPos = xpos + Random.Range(5.5f, 34.5f);

                    Instantiate(HarderPlatform, new Vector3(RandXPos, Random.Range(10, 12), 0), Rotation);
                }
            }
        }
        else
        {
            int PartyCubes = 50;

            Rainbow = true;

            if (DeathCount == 0)
            {
                PartyCubes = 500;
            }
            else if (DeathCount <= 25)
            {
                PartyCubes = 100;
            }
            else if (DeathCount >= 200)
            {
                PartyCubes = 2;
            }
            else if (DeathCount >= 100)
            {
                PartyCubes = 25;
            }

            for (int i = 0; i < PartyCubes; i++)
            {
                RandXPos = xpos + Random.Range(10, 44.5f);

                Instantiate(RainbowPartyCubes[Random.Range(0, RainbowPartyCubes.Length)], new Vector3(RandXPos, Random.Range(1, 10), 0), Rotation);
            }
        }
    }

    private void OnCollisionEnter(Collision collision)
    {
        //Touch level end (activate buttons)
        if (collision.gameObject.layer == 9 && !Dead)
        {
            if (PillarAdv + PatchAdv == 12 && !Won)
            {
                Won = true;
                TitleText.text = "You win!";

                if (DeathCount == 0)
                {
                    InfoText.text = "You didn't need to sacrifice yourself at all.\nNow this game is irrelevant to the theme!\nHave ALL the rainbow party cubes!";
                }
                else if (DeathCount == 1)
                {
                    InfoText.text = "You only sacrificed yourself 1 time. That'2 really good!\nHave some extra rainbow party cubes!";
                }
                else if (DeathCount <= 25)
                {
                    InfoText.text = "You only sacrificed yourself " + DeathCount + " times. That's really good!\nHave some extra rainbow party cubes!";
                }
                else if (DeathCount >= 200)
                {
                    InfoText.text = "You sacrificed yourself " + DeathCount + " times. What a waste!";
                }
                else if (DeathCount >= 100)
                {
                    InfoText.text = "You sacrificed yourself " + DeathCount + " times.\nHave some rainbow party cubes!";
                }
                else
                {
                    InfoText.text = "You sacrificed yourself " + DeathCount + " times. Good job!\nHave some rainbow party cubes!";
                }

                xpos = collision.transform.position.x;
                Generate();
            }
            else
            {
                if (PillarAdv == 0 && PatchAdv == 0)
                {
                    InfoText.text = "Use WASD or arrow keys to move.\n Jump with W, up or space.\nChoose a new obstacle to put into the next level.";
                }
                else
                {
                    InfoText.text = "";
                }

                TitleText.text = "Level " + (PillarAdv + PatchAdv + 1).ToString() + "/12";

                if (PillarAdv < 8)
                {
                    PillarButton.gameObject.SetActive(true);
                    PillarButtonText.text = PillarTechs[PillarAdv];
                }

                if (PatchAdv < 8)
                {
                    PatchButton.gameObject.SetActive(true);
                    PatchButtonText.text = PatchTechs[PatchAdv];
                }

                WaitingForButton = true;

                xpos = collision.transform.position.x;
            }
        }
    }

    void AdvancePillar()
    {
        PillarAdv++;

        WaitingForButton = false;
        InfoText.text = "";
        TitleText.text = "";

        if (PillarAdv == 3)
        {
            Freq += 1;
        }

        if (PillarAdv == 8)
        {
            Freq += 2;
        }

        PillarButton.gameObject.SetActive(false);
        PatchButton.gameObject.SetActive(false);

        Generate();
    }

    void AdvancePatch()
    {
        PatchAdv++;

        WaitingForButton = false;
        InfoText.text = "";
        TitleText.text = "";

        if (PatchAdv == 3)
        {
            Freq += 2;
        }

        if (PatchAdv == 8)
        {
            Freq += 3;
        }

        PillarButton.gameObject.SetActive(false);
        PatchButton.gameObject.SetActive(false);

        Generate();
    }

    private void OnCollisionStay(Collision collision)
    {
        //Jump
        if (Input.GetButton("Jump1") || Input.GetButton("Jump2"))
        {
            if (PillarAdv >= 3)
            {
                rb.velocity = new Vector3(rb.velocity.x, JumpForce * 1.5f, rb.velocity.z);
            }
            else
            {
                rb.velocity = new Vector3(rb.velocity.x, JumpForce, rb.velocity.z);
            }
        }

        //Hitting spikes
        if (collision.gameObject.layer == 8)
        {
            Dead = true;
            rb.gameObject.layer = 0;
            Renderer.material = DeadMaterial;
            rb.constraints = RigidbodyConstraints.FreezePositionZ | RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationY;
        }
    }
}
