using System.Collections;
using UnityEngine;

public class Hookshot : Projectile
{
    [SerializeField]
    private Transform hookObject;

    [SerializeField]
    private float ShotSpeed = 1;

    [SerializeField]
    private LineRenderer line;

    public override IEnumerator ProjectileLogic(Character player, float animationTime, Vector3 direction)
    {
        Block hitBlock = GetEndBlock(player.CurrentBlock, direction, ~player.Ignore);

        if (hitBlock == player.CurrentBlock)
        {
            //fire something out then back in here
            yield return StartCoroutine(lerpShot(hookObject, hookObject.position, hookObject.position + direction*10, 1.0f));
            yield break;
        }

        yield return StartCoroutine(lerpShot(hookObject, player.transform.position, hitBlock.VisualPosition, ShotSpeed * Vector3.Distance(player.transform.position,hitBlock.VisualPosition)/10));

        if (hitBlock.CurrentPlayer != null)
        {
            Block pullBlock = Block.GetOrCreateBlockAtPosition(player.CurrentBlock.position + direction, 1, ~player.Ignore);
            StartCoroutine(lerpShot(hookObject, hookObject.position, pullBlock.VisualPosition, ShotSpeed * Vector3.Distance(hookObject.position, pullBlock.VisualPosition) / 10));
            yield return player.StartCoroutine(hitBlock.CurrentPlayer.MoveToBlock(pullBlock, Character.Animation.Hit, ShotSpeed));
        }
        else
        {
            line.enabled = false;
            yield return player.StartCoroutine(player.MoveToBlock(hitBlock, Character.Animation.Jump, ShotSpeed * Vector3.Distance(player.transform.position, hitBlock.VisualPosition) / 10));
        }
    }

    private Block GetEndBlock(Block startBlock, Vector3 direction, LayerMask layerMask)
    {
        //setting up variables
        Vector3 position; // position wanted
        Block hit; //output of block detection
        Block retVal = startBlock; //block we'll actually move to

        //Check blocks in front until we hit an obstruction or went the distance
        for (int i = 1; i <= 30; i++)
        {
            //Next position to MoveTo
            position = startBlock.position + (direction * i);

            //if position is off the screen there is nothing to hit
            if (!Block.isPositionVisible(position))
                return startBlock;

            //if hit player return block they are standing on
            if (Block.isBlockAtPosition(position, 1, layerMask, out hit))
            {
                if (hit.CurrentPlayer != null)
                    return hit;
            }

            //if block block paths return block infront of it
            if (Block.isBlockAtPosition(position + Vector3.up, 1, layerMask))
            {
                return Block.GetOrCreateBlockAtPosition(position - direction, 1, layerMask);
            }
        }
        return retVal;
    }

    private IEnumerator lerpShot(Transform target, Vector3 startPosition, Vector3 endPosition, float time)
    {
        float elapsedTime = 0;

        while (elapsedTime < time)
        {
            target.position = Vector3.Lerp(startPosition, endPosition, elapsedTime / time);
            line.SetPosition(1, target.localPosition);

            yield return new WaitForEndOfFrame();
            elapsedTime += Time.deltaTime;
        }
        target.position = endPosition;
    }
}