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

public class PlayerController : MonoBehaviour {

    public GameObject Bomb;
    public GameObject Particles2D;
    public GameObject Particles2DHorizon;
    public GameObject PlayerImage;

    [SerializeField]
    public int _playerId;
    [SerializeField]
    public int _bombAmount;
    [SerializeField]
    public Color _playerColor = Color.white;
    [SerializeField]
    private float _gravityScale = 0.92f;
    [SerializeField]
    private float _vForce = 0.5f;
    [SerializeField]
    private float _hForce = 0.5f;
    [SerializeField]
    private float _turningScale = 5f;
    [SerializeField]
    private DrawPlayerPath _playerPath;
    [SerializeField]
    private float _minYVel = 0.05f;
    [SerializeField]
    private float _hDeadZone = 0.1f;
    [SerializeField]
    private float _InputDeadZone = 0.01f;
    [SerializeField]
    private float MAX_HORIZONTAL_VELOCITY = 10;
    [SerializeField]
    private float MAX_VERTICAL_VELOCITY = 10;
    [SerializeField]
    private float MIN_VERTICAL_VELOCITY = 0;
    [SerializeField]
    public Animator _cameraAnimator;

    private bool _horizontalParticlesDisplayed = true;
    

    private const float MINIMUM_VERTICAL_SPEED = 2.0f;

    private const float IDLE_TIME_DEATH = 3.0f;

    private Rigidbody2D _rigidbody;
    private int _started = 0;
    private float _tmp;
    private Vector3 _playerViewportPos;
    public Camera cam;
    private Player _player;

    private float _timingDeath;

    private float xAxisValue;
    private float yAxisValue;
    private float angle;
    private string _name;

    public string Name
    {
        get
        {
            return _name;
        }
        set
        {
            _name = value;
        }
    }

    private bool _dead = false;

    private int _score = 0;
    [SerializeField]
    private ParticleSystem _particleSystem;
    private ParticleSystem.EmissionModule em;

    public bool Dead
    {
        get
        {
            return _dead;
        }
    }

    public Color PlayerColor
    {
        get
        {
            return _playerColor;
        }
    }

    public void IncreaseScore()
    {
        _score++;
    }

    public void ResetScore()
    {
        _score = 0;
    }

    public int GetScore()
    {
        return _score;
    }
    
    void Awake() {
        
        //_playerImage = transform.Find("PlayerImage").gameObject;
        _player = ReInput.players.GetPlayer(_playerId);
        _rigidbody = GetComponent<Rigidbody2D>();
        cam = Camera.main;
        this.transform.position = new Vector3(transform.position.x, 0f, transform.position.z);
        _rigidbody.gravityScale = 0;
        PlayerImage.GetComponent<SpriteRenderer>().color = _playerColor;

        _particleSystem.GetComponent<ParticleSystemRenderer>().material.SetColor("_TintColor", _playerColor);
    }
	
    void Start()
    {
        em = _particleSystem.emission;
        _playerPath.SetColor(_playerColor);
        _timingDeath = 0f;
        StopRumble();
    }
	
	// Update is called once per frame
	void Update () {
        if (_started == 1) //When playing
        {
            //Vertical Input
            if (Mathf.Sign(transform.position.y) == Mathf.Sign(_rigidbody.velocity.y))
            {
                yAxisValue = _player.GetAxis("Propulse");
                if (Mathf.Abs(yAxisValue) > _InputDeadZone )
                {
                    if (yAxisValue != 0 && Mathf.Abs(_rigidbody.velocity.y + yAxisValue) > MIN_VERTICAL_VELOCITY && Mathf.Abs(_rigidbody.velocity.y + yAxisValue) < MAX_VERTICAL_VELOCITY)
                    {
                        em.enabled = true;
                        /*
                        if (_particleSystem.isStopped)
                        {
                            Debug.Log("Play");
                            _particleSystem.Play();
                        }*/
                        
                        if (Mathf.Sign(_rigidbody.velocity.y) != Mathf.Sign(yAxisValue))
                        {

                            yAxisValue = Mathf.Sign(yAxisValue) * _turningScale;
                        }
                        else
                        {
                            yAxisValue = Mathf.Sign(yAxisValue) * 1;
                        }
                        _rigidbody.AddForce(transform.up * _vForce * yAxisValue);
                    }
                }
                else
                {
                    
                    em.enabled = false;
                    
                    /*
                    if (_particleSystem.isPlaying)
                    {
                        //Debug.Log("Stop");
                        _particleSystem.Stop();
                    }*/
                }

            }
            //Gravity Center
            _rigidbody.gravityScale = Mathf.Sign(transform.position.y);


            //Attack
            if (_player.GetButtonDown("Attack"))
            {
                if (_bombAmount > 0)
                {
                    GameObject go = (GameObject)Instantiate(Bomb, transform.position, Quaternion.identity);
                    go.GetComponent<SpriteRenderer>().color = _playerColor;
                    go.GetComponent<BombController>()._bombId = _playerId;
                    go.GetComponent<BombController>()._player = gameObject;
                    _bombAmount--;
                    AudioManager.Instance.PlayAudio(AudioManager.AudioTracks.PlaceMine);
                }
            }  

            //Horizontal Input
            xAxisValue = _player.GetAxis("HorizontalAxis");
            if (Mathf.Abs(xAxisValue) > _InputDeadZone)
            {
                if (xAxisValue != 0 && Mathf.Abs(_rigidbody.velocity.x + xAxisValue) < MAX_HORIZONTAL_VELOCITY)
                {
                    if (Mathf.Sign(_rigidbody.velocity.x) != Mathf.Sign(xAxisValue))
                    {
                        xAxisValue = Mathf.Sign(xAxisValue) * _turningScale;
                    }
                    else
                    {
                        xAxisValue = Mathf.Sign(xAxisValue) * 1;
                    }
                    _rigidbody.AddForce(transform.right * _hForce * xAxisValue);
                }
            }
        }
        else//First Input
        {
            yAxisValue = _player.GetAxis("Propulse");
           
            if (yAxisValue != 0)
            {

                _rigidbody.AddForce(transform.up * _vForce * 200 * Mathf.Sign(yAxisValue));//First impulse
                _started = 1;
            }
            
        }

        //rotate to movement

        angle = Mathf.Atan2(_rigidbody.velocity.y, _rigidbody.velocity.x) * Mathf.Rad2Deg;
        PlayerImage.transform.rotation = Quaternion.AngleAxis(angle-90, Vector3.forward);

        //Continuum screen
        _playerViewportPos = cam.WorldToViewportPoint(transform.position);
        if (_playerViewportPos.x > 1)
        {
            _playerPath.SplitBothLines();
            transform.position = cam.ViewportToWorldPoint(_playerViewportPos - Vector3.right);
        }
        else if(_playerViewportPos.x < 0)
        {
            _playerPath.SplitBothLines();
            transform.position = cam.ViewportToWorldPoint(_playerViewportPos + Vector3.right);
        }

        //Kill inactive
        if(_started == 0)
        {
            _timingDeath += Time.deltaTime;

            if(_timingDeath > IDLE_TIME_DEATH)
            {
                KillPlayer();
            }
        }

        //Mid Particle
        
        if(_horizontalParticlesDisplayed && Mathf.Abs(transform.position.y) < 0.1 && Mathf.Abs(_rigidbody.velocity.y) > 4)
        {
            angle = Mathf.Atan2(_rigidbody.velocity.y, _rigidbody.velocity.x) * Mathf.Rad2Deg;
            _horizontalParticlesDisplayed = false;
            AudioManager.Instance.PlayAudio(AudioManager.AudioTracks.CrossLine);
            GameObject particulas = (GameObject)Instantiate(Particles2DHorizon, transform.position, Quaternion.identity);
            particulas.GetComponent<ParticleSystemRenderer>().material.SetColor("_TintColor", GameObject.FindObjectOfType<DrawCenterLine>()._lineColor);
            particulas.transform.Rotate(angle +180, -90 ,0);
            StartCoroutine(delayHorizonParticles());
        }


        
    }


    void OnTriggerEnter2D(Collider2D other)
    {
        GameObject obj = other.gameObject;
        if (obj.CompareTag("Bomb"))
        {
            if (obj.GetComponent<BombController>()._bombId != _playerId)
            {
                Destroy(obj);
                KillPlayer();
            }

        }else if (obj.CompareTag("Wall"))
        {
            KillPlayer();
        }
    }

    void KillPlayer()
    {
        _dead = true;
        GameObject particles = (GameObject)Instantiate(Particles2D, transform.position, Quaternion.identity);
        particles.GetComponent<ParticleSystemRenderer>().material.SetColor("_TintColor", _playerColor);
        //Camera.main.gameObject.AddComponent<ScreenShake>();
        //Destroy(gameObject);
        this.gameObject.SetActive(false);
        CheckPlayerHasWon();
        _playerPath.ClearPathLines();
        _timingDeath = 0;
        _cameraAnimator.SetTrigger("SoftShake");
        Rumble(1f);
        AudioManager.Instance.PlayAudio(AudioManager.AudioTracks.Death);
    }

    public void ResetPlayer()
    {
        _dead = false;
        _playerPath.ClearPathLines();
        _playerPath.StartShowingLine();
        _started = 0;
        this.gameObject.SetActive(true);
        StopRumble();
        _player = ReInput.players.GetPlayer(_playerId);
        //_rigidbody = GetComponent<Rigidbody2D>();
        //cam = Camera.main;
        //this.transform.position = new Vector3(transform.position.x, 0f, transform.position.z);
        _rigidbody.velocity = Vector3.zero;
        _rigidbody.gravityScale = 0;
        PlayerImage.GetComponent<SpriteRenderer>().color = _playerColor;
        _particleSystem.GetComponent<ParticleSystemRenderer>().material.SetColor("_TintColor", _playerColor);
    }

    private void CheckPlayerHasWon()
    {
        GameManager.Instance.CheckWinCondition();
    }


    private void Rumble(float duration)
    {
        // Set vibration for a certain duration
        foreach(Joystick j in _player.controllers.Joysticks) {
            if(!j.supportsVibration) continue;
            if(j.vibrationMotorCount > 0) j.SetVibration(0, 1.0f, duration); // 1 second duration
            if(j.vibrationMotorCount > 0) j.SetVibration(1, 1.0f, duration);
        }
    }

    private void StopRumble()
    {
        // Stop vibration
        foreach(Joystick j in _player.controllers.Joysticks) {
            j.StopVibration();
        }
    }

    private IEnumerator delayHorizonParticles()
    {
        yield return new WaitForSeconds(0.5f);

        _horizontalParticlesDisplayed = true;
    }

}
