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

public class TM_Projectile : MonoBehaviour
{
    public Vector3 vDirection;
    public Vector2 MinMax_ProjectileSpeed;

    [HideInInspector]
    public float fSpeed;

    public float SizeDeltaOverTime;

    public float fDamage = 1.0f;
    public float fDamageForce = 10.0f;

    public GameObject Prefab_Impact;

    public bool bAlwaysRotateUp;


    public Vector2 MinMax_Lifetime;

    public bool DontDestroyOnHit;
    public float DamageEveryThisOften;

    protected bool bPayloadSpent;

    protected float fDeliverPayloadTick;

    protected GameObject targetObject;

    public AudioClip clip_launchClip;
    public AudioClip clip_impactClip;
    public AudioClip clip_onDestroy;
    protected AudioSource audioSource;

    protected Vector3 vWorldPosition;

    public bool bLetSomeoneElseMoveMe;

    public int iFakeAltitude;

    private List<Action> listOnDestroy;
    private List<Action<GameObject>> listOnHitObject;

    public void Awake()
    {
        audioSource = GetComponent<AudioSource>();
        if (audioSource != null)
            audioSource.volume = TM_AudioManager.GetSFXVolume();

        listOnDestroy = new List<Action>();
        listOnHitObject = new List<Action<GameObject>>();
    }

    public virtual void Start()
    {
        float fDestroyAfter = UnityEngine.Random.Range(MinMax_Lifetime.x, MinMax_Lifetime.y);
        if (fDestroyAfter > 0.0f)
            Destroy(gameObject, fDestroyAfter);
        else
            Destroy(gameObject, 20.0f);
    }

    public void AddOnHitOtherObjectFunction(Action<GameObject> func)
    {
        listOnHitObject.Add(func);
    }

    public void AddOnDestroyFunction(Action func)
    {
        listOnDestroy.Add(func);
    }

    public virtual void Update()
    {
        if (!bLetSomeoneElseMoveMe)
        {
            UpdateMovement();
            UpdateRotation();
        }
        UpdateSize();

        if (DontDestroyOnHit)
        {
            fDeliverPayloadTick -= Time.deltaTime;
        }
    }

    public virtual void UpdateSize()
    {
        if (SizeDeltaOverTime != 0.0f)
        {
            Vector3 vScale = transform.localScale;
            vScale.x += vScale.x * SizeDeltaOverTime * Time.deltaTime;
            vScale.y += vScale.y * SizeDeltaOverTime * Time.deltaTime;
            transform.localScale = vScale;
        }
    }

    public virtual void UpdateRotation()
    {
        if (bAlwaysRotateUp)
        {
            transform.right = Vector3.Cross(Vector3.up, new Vector3(0, 0, 1));
        }
        else
            transform.right = Vector3.Cross(vDirection, new Vector3(0, 0, 1));
    }

    public virtual void UpdateMovement()
    {
        Vector3 vPos = transform.position;
        vPos += vDirection * fSpeed * Time.deltaTime;
        transform.position = vPos;
    }


    public virtual void Launch(Vector3 worldPosition, bool bSilent)
    {
        vWorldPosition = worldPosition;

        if (clip_launchClip != null && audioSource != null && !bSilent)
        {
            TM_AudioManager.PlayClip(clip_launchClip, audioSource);
        }
    }

    public virtual void OnTriggerEnter2D(Collider2D hitObject)
    {
        //Debug.Log("OMG Projectile hit a " + hitObject.gameObject.name);

        bool bShouldBeDestroyed = OnHitObject(hitObject.gameObject);
        DoImpact(transform.position);
        
        if( !bLetSomeoneElseMoveMe )
            bPayloadSpent = true;
        
        if (!DontDestroyOnHit && bShouldBeDestroyed)
        {
            Destroy(gameObject);
        }
    }

    protected virtual bool OnHitObject(GameObject hitObject)
    {
        bool bShouldBeDestroyed = true;
        TM_CombatComponent cc = hitObject.GetComponent<TM_CombatComponent>();
        if (cc != null)
        {
            if (!cc.OnHitByProjectile(this))
                bShouldBeDestroyed = false;


        }

        for (int t = 0; t < listOnHitObject.Count; t++)
            listOnHitObject[t](hitObject);

        if( bShouldBeDestroyed )    
            TM_AudioManager.PlayClip(clip_impactClip);

        return bShouldBeDestroyed;
    }

    public void OnDestroy()
    {
        for (int t = 0; t < listOnDestroy.Count; t++)
        {
            Action f = listOnDestroy[t];
            f();
        }

        TM_AudioManager.PlayClip(clip_onDestroy);

    }

    

    public virtual void OnTriggerStay2D(Collider2D hitObject)
    {
        if (bPayloadSpent)
            return;

        if (fDeliverPayloadTick > 0.0f)
            return;

        fDeliverPayloadTick = DamageEveryThisOften;
        OnHitObject(hitObject.gameObject); 
        DoImpact(transform.position);
    }

    protected void DoImpact(Vector3 pos)
    {
        if (Prefab_Impact != null)
        {
            GameObject go = Instantiate(Prefab_Impact);
            go.transform.position = pos;
            Destroy(go, 3.0f);
        }
    }

}

//Added this line rendering code from other LD games
/*

    void DrawLaserBetweenSelfAnd(GameObject target)
    {
        if (target == null)
            return;

        MeshRenderer mr = purpleLaserQuad.GetComponent<MeshRenderer>();
        mr.enabled = true;

        //Get the vector between us and them.
        Vector3 vLightningDelta = target.transform.position - laserBone.transform.position;
        float fDist = vLightningDelta.magnitude;

        //place the quad at the mid point between us and them, and rotate it to face correctly along the vector
        Vector3 lightningPos = laserBone.transform.position;
        vLightningDelta.Normalize();
        lightningPos += vLightningDelta * fDist * 0.5f;
        purpleLaserQuad.transform.position = lightningPos;
        purpleLaserQuad.transform.right = vLightningDelta;

        //scale the quad to match the distance between us and them, the variance here is for laser pulsing effect
        Vector3 pissss = purpleLaserQuad.transform.localScale;
        pissss.x = fDist;
        pissss.y = 0.1f + Random.value * 0.2f;
        purpleLaserQuad.transform.localScale = pissss;

        //Scale the texture on the quad and rotate through it
        Material lightningMaterial = purpleLaserQuad.GetComponent<MeshRenderer>().material;
        lightningMaterial.mainTextureScale = new Vector2(fDist / 4, 1);
        Vector2 vPants = lightningMaterial.mainTextureOffset;
        vPants.x += Time.smoothDeltaTime * Random.value * -12.05f;
        lightningMaterial.mainTextureOffset = vPants;

    }

*/