using UnityEngine;
using System.Collections;

public class MegaShoot : MonoBehaviour
{
    private FilteredFloat Filter = null;
    public GameObject p_Beam = null;
    public Transform MegaFirePoint = null;

    public float BeamSpeed = 5.0f;
    public float BeamDuration = 3.0f;
    public float MaxBeamSize = 10.0f;
    public float ShootTimeInterval = 5.0f;
    public float MaxTailStartSize = 2.0f;
    public float MaxTailStartSpeed = 2.0f;
    public float MaxTailLifetime = 1.0f;
    public float MaxTailGravity = 10.0f;

    public float RaiseStepFactor = 0.5f;
    public float LowerStepFactor = 0.5f;

    public float PowerUpTimeout = 10f;

    private MicrophoneInput _MicrophoneInput = null;
    private GameObject _Beam = null;

    private float _ElapsedTime = 0.0f;
    private bool _bShooting = false;
    private bool _bPreparingShoot = false;
    private bool _bCanShoot = false;

    private float _PowerUpTimer = 0f;

    private float _DefaultTailStartSize;
    private float _DefaultTailStartSpeed;
    private float _DefaultTailLifetime;
    private float _DefaultTailGravity;

    public float Intensity
    {
        get { return Filter.CurrentValue; }
    }

    public bool bCanShoot
    {
        get { return _bCanShoot; }
    }

    public bool bShooting
    {
        get { return _bShooting; }
    }

    public bool bPreparingShoot
    {
        get { return _bPreparingShoot; }
    }

    void Start()
    {
        Filter = new FilteredFloat(RaiseStepFactor, LowerStepFactor);

        if (_MicrophoneInput == null)
        {
            GameObject m = GameObject.FindGameObjectWithTag("Microphone");

            if (m != null)
            {
                _MicrophoneInput = (MicrophoneInput)m.GetComponent(typeof(MicrophoneInput));

                if (_MicrophoneInput == null)
                {
                    Debug.LogError("[" + gameObject.name + "] Microphone not found.");
                }
            }
            else
            {
                Debug.LogError("[" + gameObject.name + "] Missing GameObject named Microphone.");
            }
        }

        if (MegaFirePoint == null)
        {
            MegaFirePoint = transform.FindChild("MegaWeapon");
        }

        StoreDefaultInfo();
    }

    private void StoreDefaultInfo()
    {
        Transform VolphanteTransform = transform.FindChild("Volphante");

        if (VolphanteTransform != null)
        {
            Transform tailTransform = VolphanteTransform.FindChild("character__0013_coda");

            if (tailTransform != null)
            {
                Transform tailParticle = tailTransform.FindChild("CodaParticle");

                if (tailParticle != null)
                {
                    ParticleSystem tailEmitter = (ParticleSystem)tailParticle.GetComponent(typeof(ParticleSystem));

                    if (tailEmitter != null)
                    {
                        _DefaultTailStartSize = tailEmitter.startSize;
                        _DefaultTailStartSpeed = tailEmitter.startSpeed;
                        _DefaultTailLifetime = tailEmitter.startLifetime;
                        _DefaultTailGravity = -tailEmitter.gravityModifier;
                    }
                }
            }
        }
    }

    private void ResetDefaultInfo()
    {
        Transform VolphanteTransform = transform.FindChild("Volphante");

        if (VolphanteTransform != null)
        {
            Transform tailTransform = VolphanteTransform.FindChild("character__0013_coda");

            if (tailTransform != null)
            {
                Transform tailParticle = tailTransform.FindChild("CodaParticle");

                if (tailParticle != null)
                {
                    ParticleSystem tailEmitter = (ParticleSystem)tailParticle.GetComponent(typeof(ParticleSystem));

                    if (tailEmitter != null)
                    {
                        tailEmitter.startSize = _DefaultTailStartSize;
                        tailEmitter.startSpeed = _DefaultTailStartSpeed;
                        tailEmitter.startLifetime = _DefaultTailLifetime;
                        tailEmitter.gravityModifier = -_DefaultTailGravity;
                    }
                }
            }
        }
    }

    void Update()
    {
        if (_bCanShoot)
        {
            _PowerUpTimer += Time.deltaTime;

            if (_PowerUpTimer > PowerUpTimeout)
            {
                _bCanShoot = false;
            }
        }
        else
        {
            _PowerUpTimer = 0f;
        }

        if (_bPreparingShoot)
        {
            _ElapsedTime += Time.deltaTime;

            if (_ElapsedTime >= ShootTimeInterval)
            {
                _bPreparingShoot = false;
                _bShooting = true;

                MegaFire();
            }
            else
            {
                if (_MicrophoneInput != null)
                {
                    Filter.ToValue(_MicrophoneInput.NormalizedLoudness, Time.deltaTime);

                    if (_Beam != null)
                    {
                        Transform invertSparkTransform = _Beam.transform.FindChild("InvertSpark");

                        if (invertSparkTransform != null)
                        {
                            ParticleSystem beamEmitter = (ParticleSystem)invertSparkTransform.GetComponent(typeof(ParticleSystem));
                            if (beamEmitter != null)
                            {
                                beamEmitter.startSpeed = Filter.CurrentValue * 6.0f;
                            }
                        }

                        Transform VolphanteTransform = transform.FindChild("Volphante");

                        if (VolphanteTransform != null)
                        {
                            Transform tailTransform = VolphanteTransform.FindChild("character__0013_coda");

                            if (tailTransform != null)
                            {
                                Transform tailParticle = tailTransform.FindChild("CodaParticle");

                                if (tailParticle != null)
                                {
                                    ParticleSystem tailEmitter = (ParticleSystem) tailParticle.GetComponent(typeof(ParticleSystem));

                                    if (tailEmitter != null)
                                    {
                                        tailEmitter.startSize = Mathf.Lerp(_DefaultTailStartSize, MaxTailStartSize, Filter.CurrentValue);
                                        tailEmitter.startSpeed = Mathf.Lerp(_DefaultTailStartSpeed, MaxTailStartSpeed, Filter.CurrentValue);
                                        tailEmitter.startLifetime = Mathf.Lerp(_DefaultTailLifetime, MaxTailLifetime, Filter.CurrentValue);
                                        tailEmitter.gravityModifier = -Mathf.Lerp(_DefaultTailGravity, MaxTailGravity, Filter.CurrentValue);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        if (_bShooting)
        {
            UpdateBeam();
        }
    }

    private void UpdateBeam()
    {
        if (_Beam != null)
        {
            _ElapsedTime += Time.deltaTime;

            if (_ElapsedTime >= BeamDuration)
            {
                _ElapsedTime = 0.0f;
                _bShooting = false;

                Destroy(_Beam);

                End();
            }
            else
            {
                if (_Beam != null)
                {
                    Transform collider = _Beam.transform.FindChild("Collider");

                    if (collider != null)
                    {
                        BoxCollider2D beamCollider = (BoxCollider2D)collider.GetComponent(typeof(BoxCollider2D));

                        float growSize = BeamSpeed * Time.deltaTime;
                        float newXSize = beamCollider.size.x + growSize;

                        beamCollider.size = new Vector2(newXSize, beamCollider.size.y);
                        beamCollider.center = new Vector2(beamCollider.center.x + growSize / 2f, beamCollider.center.y);
                    }
                }
            }
        }
    }

    private void Begin()
    {
        GameManager.Instance.Stop();

        _ElapsedTime = 0.0f;
        _bPreparingShoot = true;

        if (_Beam != null)
        {
            Destroy(_Beam);
        }

        _Beam = (GameObject)Instantiate(p_Beam, MegaFirePoint.position, MegaFirePoint.rotation);

        if (Filter != null)
        {
            Filter.Reset();
        }
    }

    private void End()
    {
        _bShooting = false;

        ResetDefaultInfo();

        GameManager.Instance.Resume();
    }

    public void Shoot()
    {
        if (_bCanShoot)
        {
            _bCanShoot = false;

            Begin();
        }
        else
        {
            Debug.Log("[" + gameObject.name + "] Can't shoot");
        }
    }

    private void MegaFire()
    {
        _ElapsedTime = 0.0f;

        if (p_Beam != null)
        {
            if (MegaFirePoint != null)
            {
                if (_Beam != null)
                {
                    Transform ray = _Beam.transform.FindChild("Ray");
                    Transform collider = _Beam.transform.FindChild("Collider");

                    if (ray != null && collider != null)
                    {
                        float ySize = 0.01f;

                        if (Filter != null)
                        {
                            ySize = Mathf.Max(ySize, Filter.CurrentValue * MaxBeamSize);
                        }

                        // Particles

                        ParticleSystem beamParticle = (ParticleSystem)ray.GetComponent(typeof(ParticleSystem));

                        if (beamParticle != null)
                        {
                            if (Filter != null)
                            {
                                beamParticle.startSize = ySize;
                            }

                            beamParticle.Play();
                        }

                        // Collider

                        BoxCollider2D beamCollider = (BoxCollider2D)collider.GetComponent(typeof(BoxCollider2D));

                        if (beamCollider != null)
                        {
                            beamCollider.size = new Vector2(beamCollider.size.x, ySize);
                        }

                        // RayCollision

                        RayCollision rayCollision = (RayCollision)collider.GetComponent(typeof(RayCollision));

                        if (rayCollision != null)
                        {
                            rayCollision.SetIntensity(Filter.CurrentValue);
                        }
                    }
                }
            }
        }

        Debug.Log("[" + gameObject.name + "] MEGA FIRE [Pow = " + Filter.CurrentValue + "]");
    }

    public void EnableMegaFire()
    {
        _bCanShoot = true;
    }

    public void DisableMegaFire()
    {
        _bCanShoot = false;
    }

    void OnTriggerEnter2D(Collider2D collider)
    {
        if (collider.gameObject.tag.Equals("PowerUp"))
        {
            _bCanShoot = true;
        }
    }
}
