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

public class TM_Weapon : MonoBehaviour
{
    public TM_CombatComponent OwningCombatComponent;

    [Tooltip("Pew pew!")]
    public GameObject Prefab_Projectile;
    [Tooltip("Used for beam type weapons")]
    public bool bAttachProjectileToWeapon;

    [Tooltip("Offset from origin from which to launch projectiles. Typically the end of the weapon barrel")]
    public Vector2 vFireOriginOffset;

    [Tooltip("Multiplier for base projectile speed")]
    public float ProjectileSpeedMultiplier = 1.0f;

    [Space(12)]
    [Header("Weapon Cooldown")]
    [Tooltip("Minimum number of seconds after starting a burst to prevent further bursts.")]
    public float BurstCooldown;
    private float fBurstCooldownRemaining;

    [Space(12)]
    [Header("Burst Fire")]
    [Tooltip("Number of fire events generated from one pull of the trigger.")]
    public int ShotsPerBurst;
    [Tooltip("Delay between each fire event generated")]
    public float DelayBetweenShots;
    private int iShotsLeftInBurst;
    protected float fShotDelay;

    [Tooltip("Use for spread fire to launch multiple projectiles per fire event")]
    public List<float> AnglesToFireMultipleProjectilesFrom;

    [Tooltip("Inaccuracy measured in degrees of variance. Use for spray weapons.")]
    public float ShotInaccuracy;

    public float ScaledSize;

    //[HideInInspector]
    //public Vector3 vForceBurstToThisVector = Vector3.zero;

    [HideInInspector]
    public bool bIsFiring;

    //Vector used to generate a scalar value that increases the shot speed based on the movement of the owner
    private Vector2 vProjectileVelocityAdjustmentFromOwnerMovement;

    // Use this for initialization
    protected virtual void Start()
    {
        iShotsLeftInBurst = ShotsPerBurst;
    }

    // Update is called once per frame
    protected virtual void Update()
    {
        if (bIsFiring)
            TickDownShots();

        if (fBurstCooldownRemaining > 0.0f)
            fBurstCooldownRemaining -= Time.deltaTime;
    }

    public virtual bool StartBurst()
    {
        if (Prefab_Projectile == null)
            return false;

        //Don't re-start the burst if we're already firing
        if (bIsFiring == true)
            return false;

        //if we're on burst cooldown, don't fire
        if (fBurstCooldownRemaining > 0)
            return false;

        Fire();
        iShotsLeftInBurst--;
        if (iShotsLeftInBurst <= 0)
        {
            ResetBurst();
            bIsFiring = false;
        }
        else
        {
            bIsFiring = true;
        }

        fBurstCooldownRemaining = BurstCooldown;

        return true;
    }

    protected void ResetBurst()
    {
        iShotsLeftInBurst = ShotsPerBurst;
        fShotDelay = 0.0f;
    }

    private void TickDownShots()
    {
        fShotDelay -= Time.deltaTime;
        if (fShotDelay <= 0.0f)
        {
            fShotDelay = DelayBetweenShots;
            Fire();
            iShotsLeftInBurst--;
            if (iShotsLeftInBurst <= 0)
            {
                ResetBurst();
                bIsFiring = false;
            }
        }
    }

    protected virtual void Fire()
    {
        float fModifiedInaccuracy = Random.Range(-ShotInaccuracy, ShotInaccuracy);

        FireOneShot(fModifiedInaccuracy);
        if (AnglesToFireMultipleProjectilesFrom != null && AnglesToFireMultipleProjectilesFrom.Count > 0)
        {
            foreach (float f in AnglesToFireMultipleProjectilesFrom)
            {
                fModifiedInaccuracy = Random.Range(-ShotInaccuracy, ShotInaccuracy);
                FireOneShot(f + fModifiedInaccuracy);
            }
        }
        fShotDelay = DelayBetweenShots;

    }

    protected virtual TM_Projectile FireOneShot(float deviateAngle)
    {
        GameObject go = Instantiate(Prefab_Projectile);
        TM_Projectile p = go.GetComponent<TM_Projectile>();

        Vector3 vProjectilePosition = transform.position;
        //if there's an offset, use that instead
        if (vFireOriginOffset != Vector2.zero)
        {
            Vector2 vAdjustedOffset = TM_Utilities.Rotate2DVector(vFireOriginOffset, transform.rotation.eulerAngles.z);
            vAdjustedOffset += vAdjustedOffset*ScaledSize;
            vProjectilePosition.x += vAdjustedOffset.x;
            vProjectilePosition.y += vAdjustedOffset.y;
        }

        p.transform.position = vProjectilePosition;
        p.fSpeed *= ProjectileSpeedMultiplier;



        Vector3 towardsTarget = transform.up.normalized;

        //Override tracking        
        //if (vForceBurstToThisVector != Vector3.zero)
        //    towardsTarget = vForceBurstToThisVector.normalized;

        if (deviateAngle != 0)
        {
            Vector2 vRotMe = towardsTarget;
            vRotMe = TM_Utilities.Rotate2DVector(vRotMe, deviateAngle);
            towardsTarget.x = vRotMe.x;
            towardsTarget.y = vRotMe.y;
        }

        p.vDirection = towardsTarget;
        p.UpdateRotation();

        if (bAttachProjectileToWeapon)
        {   // Parent the projectile to this
            go.transform.parent = transform;
        }

        //if we have an adjustment vector, use it to change the speed of the projectile
        Vector2 vNormalizedAdjustment = vProjectileVelocityAdjustmentFromOwnerMovement.normalized;
        float fAdjustedSpeed = vProjectileVelocityAdjustmentFromOwnerMovement.magnitude;

        //how much of the adjustment do we want to use
        float fMultiplier = Vector2.Dot(vNormalizedAdjustment, p.vDirection)*fAdjustedSpeed;
        //Debug.Log("fMultiplier is " + fMultiplier + " when dotting " + vNormalizedAdjustment + " with " + p.vDirection + " times " + fAdjustedSpeed);
        p.fSpeed += fMultiplier;



        p.Launch(p.transform.position, OwningCombatComponent);

        //get big if we are big
        Vector3 vScale = p.gameObject.transform.localScale;
        vScale += vScale*ScaledSize;
        p.gameObject.transform.localScale = vScale;

        return p;
    }

    public void SetVelocityAdjustmentVector(Vector2 vAdjustment)
    {
        vProjectileVelocityAdjustmentFromOwnerMovement = vAdjustment;
    }
}

/* 

Good code for tracking with 2D turrets

 *     public override void UpdateMotion()
    {
        Vector3 towardsPlayer = playerScript.transform.position - transform.position;
        towardsPlayer.Normalize();
        transform.right = Vector3.Cross(towardsPlayer, new Vector3(0, 0, 1));
    }

    public override void StayVertical()
    {
       
    }

    public override void UpdateAttacks()
    {
        Vector3 towardsPlayer = playerScript.transform.position - transform.position;

        towardsPlayer.x += -0.2f + Random.value*0.4f;
        towardsPlayer.Normalize();

        for (int t = 0; t < Attacks.Count(); t++)
        {
            Attacks[t].Update();

            if (transform.position.x < 12.0f)
            {
                float fShotSpeed = 15.0f + (5.5f * mcs.GetEnemySpeedMultiplier());
                Attacks[t].TryFire(transform.position, towardsPlayer, fShotSpeed);
            }
        }
    }
*/
