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

public class Orquestator : MonoBehaviour
{
    public GameObject _plug;
    public GameObject _bulb;
    public GameObject _failure;
    public GameObject _camera;
    public Text _length;

    public float _minSpeed = 1.0f;
    public float _maxSpeed = 5.0f;
    public float _maxDistanceSpeed = 10.0f;
    public float _minDistanceSpeed = 0.6f;
    public float _clickOffset = 10.02f;

    public float _initialPitch = 1.0f;
    public float _maxPitch = 1.2f;

    public float _maxLength = 20.0f;
    public float _distanceLengthRatio = 5.0f;

    public bool compleated, zoomed, offedfinished;
    public bool creditsLaunch = false, retryLaunched = false;

    private Vector2 _currentPlugPosition;
    private bool following, playing;
    private float distance, separation;

    public float _maxSeparationAnimation = 30.0f;

    public float _maxIntensityPS = 1.0f;
    public float _minIntensityPS = 0.1f;

    public int _minSpotAngle;
    public float _minIntensity;
    public int _maxSpotAngle;
    public float _maxIntensity;

    public int _minSpotAngleLimit = 110;
    public float _minIntensityLimit = 2.5f;

    public int _maxSpotAngleLimit = 150;
    public float _maxIntensityLimit = 4.15f;

    private int _maxStepsLimit = 100;
    private int _maxSteps = 100;
    private int _minSteps = 30;

    private float targetOrtho;

    private int _step;
    private bool _glowing;

    private AudioSource _cordSound;

    void Start()
    {
        _currentPlugPosition = _plug.transform.position;
        _length.text = String.Format("{0} m", _maxLength.ToString("0.0"));
        playing = true;
        following = false;
        distance = 0.0f;
        separation = Vector2.Distance(_plug.transform.position, _bulb.transform.position);
        compleated = false;
        zoomed = false;
        offedfinished = false;

        _cordSound = GetComponent<AudioSource>();
        _cordSound.pitch = _initialPitch;

        _maxSteps = _maxStepsLimit;
        _glowing = true;
        _step = 0;

        Light light = _plug.transform.Find("light").gameObject.GetComponent<Light>();
        light.intensity = _minIntensity;
        light.spotAngle = _minSpotAngle;

        _minSpotAngle = _minSpotAngleLimit;
        _minIntensity = _minIntensityLimit;
        _maxSpotAngle = _maxSpotAngleLimit;
        _maxIntensity = _maxIntensityLimit;

        targetOrtho = Camera.main.orthographicSize;
    }

    void Update()
    {
        if (compleated)
        {
            playing = false;
        }

        if (playing)
        {
            if (Input.GetMouseButtonDown(0) && ((Camera.main.ScreenToWorldPoint(Input.mousePosition) - _plug.transform.position).magnitude <= _clickOffset))
            {
                following = true;
            }

            if (Input.GetMouseButtonUp(0))
            {
                following = false;
            }
        }
        else
        {
            following = false;
        }
    }

    void FixedUpdate()
    {
        if (!playing)
        {
            if (compleated)
            {
                if (!offedfinished)
                {
                    _plug.GetComponent<Rigidbody2D>().constraints = RigidbodyConstraints2D.FreezePositionX | RigidbodyConstraints2D.FreezePositionY;

                    GameObject plug = _plug.transform.Find("plug").gameObject;
                    plug.GetComponent<SpriteRenderer>().enabled = false;

                    GameObject light = _plug.transform.Find("light").gameObject;
                    light.GetComponent<Light>().enabled = false;

                    GameObject bulb = _bulb.transform.Find("bulb").gameObject;
                    bulb.GetComponent<SpriteRenderer>().enabled = false;

                    GameObject embedded = _bulb.transform.Find("bulbEmbeded").gameObject;
                    embedded.GetComponent<SpriteRenderer>().enabled = true;

                    GameObject bulbLight = _bulb.transform.Find("light").gameObject;
                    bulbLight.GetComponent<Light>().enabled = true;

                    GameObject ending = transform.Find("Ending").gameObject;
                    ending.GetComponent<AudioSource>().Play(0);

                    offedfinished = true;
                }

                if (!zoomed)
                {
                    targetOrtho = Camera.main.orthographicSize;
                    targetOrtho -= -1.0f * 1.0f;
                    targetOrtho = Mathf.Clamp(targetOrtho, 1.0f, 17.0f);

                    Camera.main.orthographicSize = Mathf.MoveTowards(Camera.main.orthographicSize, targetOrtho, 3.0f * Time.deltaTime);
                    _camera.transform.position = Vector3.MoveTowards(_camera.transform.position, new Vector3(23.0f, 14.0f, -10.0f), 6.0f * Time.deltaTime);
                }

                if (!creditsLaunch)
                {
                    StartCoroutine(CreditsWait());
                    creditsLaunch = true;
                }
            }
            else
            {
                _failure.GetComponent<Text>().enabled = true;

                if (!retryLaunched)
                {
                    StartCoroutine(Reload());
                    retryLaunched = true;
                }
            }

            _cordSound.enabled = false;
        }

        if (following)
        {
            float _xRel = (Camera.main.ScreenToWorldPoint(Input.mousePosition) - _plug.transform.position).x;
            float _yRel = (Camera.main.ScreenToWorldPoint(Input.mousePosition) - _plug.transform.position).y;

            float xSpeed = 0.0f;
            if (Math.Abs(_xRel) > _minDistanceSpeed)
            {
                xSpeed = _xRel * _maxSpeed / _maxDistanceSpeed;
                if (Math.Abs(xSpeed) < _minSpeed) xSpeed = _minSpeed * xSpeed < 0 ? -1.0f : 1.0f;
            }

            float ySpeed = 0.0f;
            if (Math.Abs(_yRel) > _minDistanceSpeed)
            {
                ySpeed = _yRel * _maxSpeed / _maxDistanceSpeed;
                if (Math.Abs(ySpeed) < _minSpeed) ySpeed = _minSpeed * ySpeed < 0 ? -1.0f : 1.0f;
            }

            _plug.GetComponent<Rigidbody2D>().velocity = new Vector2(xSpeed, ySpeed);

            distance += Vector2.Distance(_plug.transform.position, _currentPlugPosition);
            _currentPlugPosition = _plug.transform.position;

            float left = _maxLength - (distance / _distanceLengthRatio);
            if (left < 0.0f) left = 0.0f;
            if (left == 0.0f) playing = false;

            float pitch = _initialPitch + (float)Math.Pow(((Math.Sin((90.0f + ((left / _maxLength) * 90.0f)) * (Math.PI / 180.0f)))), 3.0f) * (_maxPitch - _initialPitch);
            _cordSound.pitch = pitch;

            _length.text = String.Format("{0} m", (_maxLength - (distance / _distanceLengthRatio)).ToString("0.0"));
        }
        else
        {
            _plug.GetComponent<Rigidbody2D>().velocity = new Vector2(0.0f, 0.0f);
        }

        if (!compleated)
        {
            _step++;
            separation = Vector2.Distance(_plug.transform.position, _bulb.transform.position);
            if (separation > _maxSeparationAnimation) separation = _maxSeparationAnimation;

            _maxSteps = _minSteps + (int)((_maxStepsLimit - _minSteps) * (separation / _maxSeparationAnimation));

            _maxIntensity = _maxIntensityLimit * (_maxIntensityPS - ((_maxIntensityPS - _minIntensityPS) * (((distance / _distanceLengthRatio)) / _maxLength)));
            _minIntensity = _minIntensityLimit * (_maxIntensityPS - ((_maxIntensityPS - _minIntensityPS) * (((distance / _distanceLengthRatio)) / _maxLength)));

            _maxSpotAngle = (int) (_maxSpotAngleLimit * (_maxIntensityPS - ((_maxIntensityPS - _minIntensityPS) * (((distance / _distanceLengthRatio)) / _maxLength))));
            _minSpotAngle = (int) (_minSpotAngleLimit * (_maxIntensityPS - ((_maxIntensityPS - _minIntensityPS) * (((distance / _distanceLengthRatio)) / _maxLength))));
            
            float intensityIncrement = ((_maxIntensity - _minIntensity) / _maxSteps) * _step;
            float spotAngleIncrement = ((_maxSpotAngle - _minSpotAngle) / (float)_maxSteps) * _step;

            float intensity = 0.0f;
            int spotAngle = 0;
            if (_glowing)
            {
                intensity = _minIntensity + intensityIncrement;
                spotAngle = _minSpotAngle + (int)spotAngleIncrement;
            }
            else
            {
                intensity = _maxIntensity - intensityIncrement;
                spotAngle = _maxSpotAngle - (int)spotAngleIncrement;
            }

            if (_step >= _maxSteps)
            {
                _step = 0;
                _glowing = !_glowing;
            }

            Light plugLight = _plug.transform.Find("light").gameObject.GetComponent<Light>();
            plugLight.intensity = intensity;
            plugLight.spotAngle = spotAngle;
        }
    }

    IEnumerator CreditsWait()
    {
        yield return new WaitForSeconds(5);

        GameObject credits = transform.Find("Credits").gameObject;
        credits.transform.Find("canvasImageCredits").gameObject.GetComponent<Canvas>().enabled = true;
        credits.transform.Find("canvasTextCredits").gameObject.GetComponent<Canvas>().enabled = true;
    }

    IEnumerator Reload()
    {
    
        yield return new WaitForSeconds(5);

        Scene scene = SceneManager.GetActiveScene();
        SceneManager.LoadScene(scene.name);

    }
}