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

public class Player : MonoBehaviour {

    public float speed = 6.0F;
    private float _jumpSpeed = 8.0F;
    private float _gravity = 20.0F;
    private Vector2 _moveDirectionXZ = Vector3.zero;
    private float _moveY = 0;

    public IKTest IKControl;

    [SerializeField] private SkinnedMeshRenderer _renderer;
    [SerializeField] private Animator _animator;
    [SerializeField] private ParticleSystem _fireParticles;

    [SerializeField] private float _accelSpeed = 2;
    [SerializeField] private float _deccelSpeed = 2;
    [SerializeField] private Transform _model;
    [SerializeField] private Transform _hoverPoint;
    [SerializeField] private float _rotateSmooth = 3;

    private CharacterController _controller;
    private Collider _collider;

    void Awake()
    {
        _controller = GetComponent<CharacterController>();
        _collider = _controller.GetComponent<Collider>();
        GameController.Instance.SetupMaterialForPortals(_renderer);
    }

	
	// Update is called once per frame
	void Update () 
    {
        UpdateMovement(new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical")), _controller.isGrounded);

        if (_controller.isGrounded) 
        {
            if (Input.GetButton("Jump"))
                _moveY = _jumpSpeed;          
        }

        Vector3 finalMovement = new Vector3(_moveDirectionXZ.x, _moveY, _moveDirectionXZ.y);

        ModelLookAt(finalMovement);
        HandleAnimation();

        _controller.Move(finalMovement * Time.deltaTime);
    }

    private void UpdateMovement(Vector2 input, bool grounded)
    {
        if(input != Vector2.zero)
            input = input.normalized;

        if (grounded)
        {
            _moveY = -0.1f;

            if (input == Vector2.zero)
                _moveDirectionXZ = Vector2.MoveTowards(_moveDirectionXZ, Vector2.zero, _deccelSpeed * Time.deltaTime);
            else
                _moveDirectionXZ += input * _accelSpeed * Time.deltaTime;
        }
        else
        {
            _moveY -= _gravity * Time.deltaTime;
            _moveDirectionXZ = Vector2.MoveTowards(_moveDirectionXZ, Vector2.zero, _deccelSpeed * Time.deltaTime * 0.3f);
        }


        if(_moveDirectionXZ.magnitude > speed)
        {
            _moveDirectionXZ = _moveDirectionXZ.normalized * speed;
        }
    }

    private void ModelLookAt(Vector3 direction)
    {
        Vector3 LookDir = new Vector3(direction.x, 0, direction.z);

        if (LookDir == Vector3.zero || LookDir.magnitude < 0.0001)
            return;

        LookDir.y = 0;
        var targetRot = Quaternion.LookRotation(LookDir);

		_model.rotation = Quaternion.Slerp(_model.rotation, targetRot, _rotateSmooth * Time.deltaTime);
    }

    public Vector3 GetHoverPoint()
    {
        return _hoverPoint.position;
    }

    public Collider GetCollider()
    {
        return _collider;
    }


    private float runAmount = 0;
    private float headHangAmount = 0;
    private float holdingAmount = 0;

    private void HandleAnimation()
    {
        float moveAmount = _moveDirectionXZ.magnitude / speed;
        _animator.SetFloat("fMoveAmount", moveAmount);

        if (moveAmount > 0.9f)
            runAmount += Time.deltaTime * 0.5f;
        else
            runAmount -= Time.deltaTime;

        runAmount = Mathf.Clamp01(runAmount);
        _animator.SetFloat("fRunAmount", runAmount);



        if(!Cursor.visible)
            headHangAmount += Time.deltaTime;
        else
            headHangAmount -= Time.deltaTime;

        headHangAmount = Mathf.Clamp01(headHangAmount);
        _animator.SetLayerWeight(2, headHangAmount);



        if( _holding != null)
            holdingAmount += Time.deltaTime * 1.3f;
        else
            holdingAmount -= Time.deltaTime * 1.3f;

         holdingAmount = Mathf.Clamp01( holdingAmount);

         IKControl.Amount = holdingAmount;
    }


    private Grabable _holding;
    public void HoldingGrabable(Grabable package)
    {
        _holding = package;
        IKControl._ikTarget = package.transform;
    }

    public void ReleasedPackage()
    {
        _holding = null;
        IKControl._ikTarget = null;
    }


    public void Fired()
    {
        _fireParticles.gameObject.SetActive(true);
    }
}
