﻿using UnityEngine;
using System.Collections;

public class PlayerController : MonoBehaviour {

    // movement variables

    #region current values
    //gravity and jumping
    public float gravity = -50f;
    public float inAirDamping = 3f;
    public float jumpHeight = 5f;
//	public float jumpHeightIncrease = 10f;
    public float jumpGravity = -20f; //current jump force 
	private bool _useJumpGravity = false;
    private bool _jump = false;
	private bool growing = false;

	public int multipleJumps = 2;

	private float defaultRunspeed;

    //walking
    public float runSpeed = 15f;
    public float groundDamping = 5f; // how fast do we change direction? higher means faster

    //taking damage
    private bool _isTakingDamage = false;
    public float damageCooldown = 0.2f; // How long player sprite keeps flashing after taking damage
  
    //other
    public float mass = 1.0f;
    #endregion

    [HideInInspector]
    private float _rawMovementDirection = 1;
    [HideInInspector]
    private float normalizedHorizontalSpeed = 0;

    // References to gameobject's components
    private CharacterController2D _controller;
    public CharacterController2D Controller { get { return _controller; } set { _controller = value; } }

	//private plantGrow _plantGrow;

    private Animator _animator;
    private RaycastHit2D _lastControllerColliderHit;
    private Vector3 _velocity;
 //   [SerializeField] private AudioSource _audioSource;
//    SoundManager _soundManager;

    private Transform _spriteTransform;
    public Transform SpriteTransform { get { return _spriteTransform; } set { _spriteTransform = value; } }

    private SpriteRenderer _spriteRenderer;

    //Animator component's parameters
    private int runParam;
    private int jumpParam;
    private int dashParam;


    int oneWayPlatformLayer;

	public soundManager manager;

    //private InputManager input;
   // private SoundManager soundManager;
	private Vector3 startPos;

   // #region monobehavior methods

    void Awake()
    {
        //input = GameObject.Find(GameObjectNames.INPUT_MANAGER).GetComponent<InputManager>();

		defaultRunspeed = runSpeed;

		startPos = transform.position;
        // Find the components
        _animator = GetComponent<Animator>();
        _controller = GetComponent<CharacterController2D>();
        _controller.onControllerCollidedEvent += onControllerCollider;

	//	_plantGrow = GetComponent<plantGrow>();

        _spriteTransform = GetComponent<Transform>();
        _spriteRenderer = GetComponent<SpriteRenderer>();

        // get int hashes for animator state parameters for efficiency 
        runParam = Animator.StringToHash("run");
        jumpParam = Animator.StringToHash("jump");
        dashParam = Animator.StringToHash("dash");

        // copy default values
   //     AssignDefaultValues();

		//GetComponent<BoxCollider2D>()

    }


	public void setActivation(bool a) {

		//tänne kaikki mitä tarvitaan tämän controllerin järkevään
		//sammuttamiseen/käynnistämiseen

		//pallon käynnistyessä
		if (!a) {
			gameObject.SetActive(false);
			_controller.isGrounded = false;
			
		} else { //pallon loppuessa

			if (_controller) {			
				_controller.resetVelocity();
			}


			gameObject.SetActive(true);
			SetAnimation(jumpParam, true);
		}

	}

	public void resetPosition(Vector2 pos) {

		transform.position = pos;
	}

    void Start()
    {
         oneWayPlatformLayer = LayerMask.NameToLayer("OneWay");
		
		InvokeRepeating ("addSpeed", 10, 10);
	}
	
	void addSpeed() {

		runSpeed += 0.6f;
		defaultRunspeed += 0.6f;
	}

	private int currentJumps = 0;
	void Update()
    {
        // grab our current _velocity to use as a base for all calculations
        _velocity = _controller.velocity;
		normalizedHorizontalSpeed = 0;
	//	Debug.Log (Input.GetAxisRaw("Horizontal"));
		//jos pysähtyy nollataan spiidiboosit
		if (_velocity.x < 0.2f)
			runSpeed = defaultRunspeed;

		if (Input.GetAxisRaw("Horizontal") < 0)
			normalizedHorizontalSpeed = -1f;
		if (Input.GetAxisRaw("Horizontal") > 0)
			normalizedHorizontalSpeed = 1f;


		if (_controller.isGrounded) {
			_velocity.y = 0;
			currentJumps = 0;
		}

		if (Input.GetButtonUp("Fire1")) {
			_useJumpGravity = false;
		}

		if (Input.GetButtonDown("Fire1")) {
			if (currentJumps < multipleJumps) {
				_useJumpGravity = true;
				_jump = true;	
				manager.playSound("jump"); //hyppyään

				_velocity.y = Mathf.Sqrt(2f * jumpHeight * -gravity);
				if (currentJumps == 1) {
				
					runSpeed += 1;
					_velocity.x = Mathf.Sqrt(4f * jumpHeight * -gravity);
				}
				


				currentJumps++;
			}
			
		}

        // we can only jump whilst grounded
        if (_controller.isGrounded && _jump)
        {
			   
 
            //_animator.Play(Animator.StringToHash("Jump"));
       //     SetAnimation(jumpParam, true);
        }

        // apply horizontal speed smoothing it
        var smoothedMovementFactor = _controller.isGrounded ? groundDamping : inAirDamping; // how fast do we change direction?
        _velocity.x = Mathf.Lerp(_velocity.x, normalizedHorizontalSpeed * _rawMovementDirection * runSpeed, Time.deltaTime * smoothedMovementFactor);

        // jumpGravity affects only when going up, otherwise use default gravity.
        if (_velocity.y < 0)
        {
            _useJumpGravity = false;
		//	jumpHeight = _defaultJumpHeight;
 //          _animator.SetBool(jumpParam, true);
        }
    

        // apply gravity before moving
        if (_useJumpGravity)
        {
            _velocity.y += jumpGravity * Time.deltaTime;
        }
        else
        {
            _velocity.y += gravity * Time.deltaTime;
        }

		_controller.move(_velocity * Time.deltaTime);


    }

 //   #endregion


    public void SetAnimation(int param, bool value)
    {
        _animator.SetBool(param, value);
    }

    public void SubsribeToInput(bool subscribe)
    {
//        var input = GameObject.Find(GameObjectNames.INPUT_MANAGER).GetComponent<InputManager>();
        /*
        if (subscribe)
        {
            // adds event listeners to input manager's events
            input.OnAxis += PlayerAxis;
            input.OnADown += PlayerADown;
            input.OnAUp += PlayerAUp;
            input.OnBDown += PlayerBDown;
            input.OnBUp += PlayerBUp;
            input.OnXDown += PlayerXDown;
            input.OnXUp += PlayerXUp;
            input.OnYDown += PlayerYDown;
            input.OnYUp += PlayerYUp;

            _isSubscribedToInput = true;

        }
        else if (!subscribe)
        {
            // drops event listeners from input manager's events
            input.OnAxis -= PlayerAxis;
            input.OnADown -= PlayerADown;
            input.OnAUp -= PlayerAUp;
            input.OnBDown -= PlayerBDown;
            input.OnBUp -= PlayerBUp;
            input.OnXDown -= PlayerXDown;
            input.OnXUp -= PlayerXUp;
            input.OnYDown -= PlayerYDown;
            input.OnYUp -= PlayerYUp;

            _isSubscribedToInput = false;
        }*/
    }

    void onControllerCollider(RaycastHit2D hit)
    {
        _jump = false;
		currentJumps = 0;
        //SetAnimation(jumpParam, false);

        // bail out on plain old ground hits
        if (hit.normal.y == 1f)
            return;

        // logs any collider hits if uncommented
        //Debug.Log( "flags: " + _controller.collisionState + ", hit.normal: " + hit.normal );
    }

    public void TakeDamage(int damageAmmount)
    {
        // Stop this script's all running coroutines
        StopAllCoroutines();

        StartCoroutine(DamagePenalty());
    }

    private float _takingdamageLength = 0.5f;

    private IEnumerator DamagePenalty()
    {
        /*
        //slide opposite direction of damage origin
        gravity = 0;
        jumpGravity = 0;
        runSpeed = damageSlidingSpeed;
        normalizedHorizontalSpeed = -Mathf.Sign(_spriteTransform.localScale.x);

        _isTakingDamage = true;
        _animator.SetBool(isTakingDamageParam, _isTakingDamage);

        // lose controls over character
        if (_isSubscribedToInput)
        {
            SubscribeToInput(false);
        }

        yield return new WaitForSeconds(_takingdamageLength);

        // start flashing sprite to indicate immortality
        StartCoroutine(DamageCooldown());

        //regain controls 
        if (!_isSubscribedToInput)
        {
            SubscribeToInput(true);
        }

        RestoreDefaultValues();

        _isTakingDamage = false;
        _animator.SetBool(isTakingDamageParam, _isTakingDamage);

         */
        yield return null;
         
    }

    private IEnumerator DamageCooldown()
    {
        Debug.Log("flashing");

        // flash sprite 
        for (int i = 0; i < 10; i++)
        {
            Debug.Log("flashing round");
            _spriteRenderer.color = new Color(_spriteRenderer.color.r, _spriteRenderer.color.g, _spriteRenderer.color.b, 0.25f);
            yield return new WaitForSeconds(damageCooldown);
            _spriteRenderer.color = new Color(_spriteRenderer.color.r, _spriteRenderer.color.g, _spriteRenderer.color.b, 1f);
            yield return new WaitForSeconds(damageCooldown);
        }
    }
  //  #endregion

}
//game