using UnityEngine;
using System.Collections;
using System.Collections.Generic;

namespace RollingRockRumble {
    public class RockHandler : MonoBehaviour {

        private Rigidbody2D rb2D;

        public float rockAcceleration;

        public bool invertedWheel = false;
        public bool isGrounded = false;
        public float timeSinceGrounded = 0f;

        private float tempScrollDelta;
        private float speedFactor = 10.0f;
        private float accelerationFactor = 10f; // TODO : option to change this (mouse wheel sensitivity)
        private float baseGravity = 0.9f;



        public float currentLife = 1f;
        private float lifeMax = 2f;
        private float lifeBonusIncrease = 0.025f;
        private float lifeMalusDecrease = 0.1f;
        private float lifeTimeDecrease = 0.025f;
        private float timeBetweenLifeDecreases = 10f;
        private float LifeDecreaseTimeFactor = 0.99f;
        private float nextTimeLifeDecrease;


        public GameObject lifeSprite;

        public GameHandler gameHandler;

        public GameObject objectMusic;
        


        void Start() {
            rb2D = GetComponent<Rigidbody2D>();
            rockAcceleration = 0f;
            gameHandler = GameObject.Find("GAME").GetComponent<GameHandler>();
            nextTimeLifeDecrease = Time.time + timeBetweenLifeDecreases;
            timeBetweenLifeDecreases *= LifeDecreaseTimeFactor;
        }



        void FixedUpdate() {
            if (rockAcceleration > 0) {
                objectMusic.GetComponent<AudioSource>().pitch = Mathf.Max(Mathf.Min(rockAcceleration * 0.025f, 1f), 0.3f);
            }
            else {
                objectMusic.GetComponent<AudioSource>().pitch = Mathf.Max(Mathf.Min(rockAcceleration * 0.025f, -0.3f), -1f);
            }
            if (!gameHandler.pauseGame) {
                tempScrollDelta = Input.GetAxis("Mouse ScrollWheel")*10f;
                
                //Debug.Log("Mouse wheel value = " + tempScrollDelta);
                //Debug.Log("isGrounded == " + isGrounded);

                if (tempScrollDelta != 0f) {
                    if (invertedWheel) {
                        rockAcceleration += tempScrollDelta * accelerationFactor;
                    }
                    else {
                        rockAcceleration -= tempScrollDelta * accelerationFactor;
                    }
                    rockAcceleration = Mathf.Max(Mathf.Min(rockAcceleration, 100f), -100f);
                }
                else {
                    rockAcceleration *= 0.98f;
                }
                rb2D.MoveRotation(rb2D.rotation + rockAcceleration * speedFactor * Time.fixedDeltaTime);

                //the rock will feel lighter when moving, helping it to roll along walls and ceilings
                if (Mathf.Abs(rockAcceleration) > 1f) {
                        rb2D.gravityScale = baseGravity / Mathf.Pow(Mathf.Abs(rockAcceleration), 0.1f);
                }
                else {
                    rb2D.gravityScale = baseGravity;
                }

                //Debug.Log("gravityScale = " + rb2D.gravityScale);

                //Debug.Log("TransformDirection = " + transform.TransformDirection(Vector3.left) * 1.5f);
                //Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.left) * 1.5f, Color.green);

                if ((isGrounded) && ((timeSinceGrounded + 0.15f) < Time.time)) {
                    isGrounded = false;
                }

                if (Application.loadedLevelName == "game") {
                    if (nextTimeLifeDecrease < Time.time) {
                        currentLife -= lifeTimeDecrease;
                        nextTimeLifeDecrease = Time.time + timeBetweenLifeDecreases;
                    }

                    if (currentLife <= 0f) {
                        gameHandler.GameOver();
                    }
                }

            }
            else {
                //game paused
            }
        }



        void OnCollisionEnter2D(Collision2D coll) {
            if ((coll.gameObject.tag == "Wall") ||
                (coll.gameObject.tag == "Slope") ||
                (coll.gameObject.tag == "Spawner")) {
                isGrounded = true;
                timeSinceGrounded = Time.time;
                if (coll.gameObject.name.Contains("Bump")) {
                    float tempDistance = Vector2.Distance(Vector2.zero, ((GetComponent<Rigidbody2D>().velocity * 0.25f) + coll.contacts[0].normal) / 2f);
                    if (tempDistance > 0.3f) {
                        AudioSource tempSFX = GameObject.Find("SFXBoulderBounce").GetComponent<AudioSource>();
                        tempSFX.transform.position = transform.position;
                        tempSFX.volume = gameHandler.optionVolume * Mathf.Min((tempDistance - 0.3f) * 0.1f, 1f);
                        tempSFX.Play();
                        Debug.DrawLine(coll.contacts[0].point, coll.contacts[0].point + ((GetComponent<Rigidbody2D>().velocity * 0.25f) + coll.contacts[0].normal) / 2f, Color.red, 3f, false);
                        

                    }
                }
            }
            /*
            if (coll.gameObject.tag == "Creature") {
                coll.gameObject.GetComponent<CreatureHandler>().CreatureHit();
                MakeCreatureLoseLevels(coll.gameObject);
            }
            */
        }



        void OnCollisionStay2D(Collision2D coll) {
            if ((coll.gameObject.tag == "Wall") ||
                (coll.gameObject.tag == "Slope") ||
                (coll.gameObject.tag == "Spawner")) {
                isGrounded = true;
                timeSinceGrounded = Time.time;
            }
            /*
            if (coll.gameObject.tag == "Creature") {
                MakeCreatureLoseLevels(coll.gameObject);
            }
            */
        }



        void OnTriggerEnter2D(Collider2D other) {
            if (other.gameObject.tag == "Creature") {
                other.transform.parent.gameObject.GetComponent<CreatureHandler>().CreatureHit();
                //if (other.transform.parent.gameObject.GetComponent<CreatureHandler>().creatureLevel == 1) {
                    //if creature level==1, then it is destroyed when the player touches this trigger, thus no inertia loss due to collision
                    KillCreature(other.transform.parent.gameObject);
                //}
            }
        }


        /*
        void OnTriggerStay2D(Collider2D other) {
            if (other.gameObject.tag == "Creature") {
                if (other.transform.parent.gameObject.GetComponent<CreatureHandler>().creatureLevel == 1) {
                    //if creature level==1, then it is destroyed when the player touches this trigger, thus no inertia loss due to collision
                    KillCreature(other.transform.parent.gameObject);
                }
            }
        }
        */


        void KillCreature(GameObject creatureToKill) {
            creatureToKill.GetComponent<CreatureHandler>().CreatureKilled();
            //player diameter increases, gravity too
            currentLife = Mathf.Min(currentLife + lifeBonusIncrease, lifeMax);
            UpdateLifeSprite();
        }



        void UpdateLifeSprite() {
            lifeSprite.transform.localScale = new Vector3(lifeSprite.transform.localScale.x, currentLife, 1f);
            lifeSprite.transform.localPosition = new Vector3(lifeSprite.transform.localPosition.x,
                                                            -0.755f + currentLife/2f * 0.755f,
                                                            0f);
        }



        public void DecreaseDiameter() {
            currentLife = Mathf.Max(currentLife - lifeMalusDecrease, 0f);
            UpdateLifeSprite();
        }



        void MakeCreatureLoseLevels(GameObject objectCreature) {
            //if creature is lvl 2+, the player hits the creature's collision box and is slowed
            //and the creature's level decreases based on player speed (0 to 3 level loss)
            int levelLoss = Mathf.FloorToInt((Mathf.Abs(rockAcceleration) / 2.99f) + 0.5f); //more chances to have 1 or 2 level loss than 0 or 3
            objectCreature.GetComponent<CreatureHandler>().HasBeenHit(levelLoss);
        }
    }
}
