using System;
using UnityEngine;
using System.Collections;

public class TM_Projectile : MonoBehaviour
{
    public Vector3 vDirection;

    public Vector2 SpeedMinMax;
    
    [HideInInspector]
    public float fSpeed;

    public float SizeDeltaOverTime;

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

    public GameObject Prefab_Impact;

    public bool bAlwaysRotateUp;


    public float fDestroyAfter;

    public bool DontDestroyOnHit;
    public float DamageEveryThisOften;
    public bool PassThroughWorldCollision;

    protected bool bPayloadSpent;

    protected float fDeliverPayloadTick;

    protected GameObject targetObject;

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

    protected Vector3 vWorldPosition;

    [HideInInspector] public TM_CombatComponent owningCombatComponent;

    public float ApplyFreezeTimer;

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

        fSpeed = UnityEngine.Random.Range(SpeedMinMax.x, SpeedMinMax.y);
    }

    public virtual void Start()
    {
        if (fDestroyAfter > 0.0f)
            Destroy(gameObject, fDestroyAfter);
        else
            Destroy(gameObject, 20.0f);
    }

    public virtual void Update()
    {
        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()
    {
        TM_SproggiwoodCoinMotionComponent sprog = GetComponent<TM_SproggiwoodCoinMotionComponent>();
        if (sprog != null && sprog.enabled)
        {
            Vector3 vOldPos = transform.position;
            transform.position = sprog.GetCurrentPosition();
            vDirection = (transform.position - vOldPos).normalized;

            if (sprog.ArrivedAtGoal())
            {
                DoImpact(transform.position);
            }
        }
        else
        {
            Vector3 vPos = transform.position;
            vPos += vDirection*fSpeed*Time.deltaTime;
            transform.position = vPos;
        }
    }


    public virtual void Launch(Vector3 worldPosition, TM_CombatComponent owner)
    {
        owningCombatComponent = owner;
        vWorldPosition = worldPosition;

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

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

        OnHitObject(hitObject.gameObject);
        DoImpact(transform.position);
        bPayloadSpent = true;

        if ((!PassThroughWorldCollision && hitObject.gameObject.layer == LayerMask.NameToLayer("WorldCollision")) ||
            !DontDestroyOnHit)
        {
            Destroy(gameObject);
        }
    }

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

        return true;
    }

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

        if (fDeliverPayloadTick > 0.0f)
            return;

        fDeliverPayloadTick = DamageEveryThisOften;
        DoImpact(transform.position);
    }

    protected virtual void DoImpact(Vector3 pos)
    {
        if (Prefab_Impact != null)
        {
            GameObject go = Instantiate(Prefab_Impact);
            go.transform.position = pos;
            TM_Utilities.PointSpriteInDirection(UnityEngine.Random.insideUnitCircle, go);
            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;

    }

*/