using UnityEngine;
using System.Collections;
using Gamelogic.Grids2;
public class ActionSlam : TurnAction
{
    private GridPoint2 direction;

    public ActionSlam(GridPoint2 direction)
    {
        this.direction = direction;
    }

    override public void Perform()
    {
        GridPoint2 land = GetLanding(CombatLib.Player, true);
        TurnAction movePlayer = GetPlayerMove(land);
        TurnAction moveSlammee = GetTargetMove(land);

        movePlayer.FollowupAction = moveSlammee;

        TurnBasedGameLoop.instance.ExecuteActionImmediate(movePlayer);
    }

    private static TurnAction GetPlayerMove(GridPoint2 land)
    {
        float time = GetTime(PointyHexPoint.HexNorm(CombatLib.Player.Location - land));

        TurnAction movePlayer = new ActionMove(CombatLib.Player, CombatLib.Player.Location, land, time);        
        return movePlayer;
    }

    private TurnAction GetTargetMove(GridPoint2 land)
    {
        if (!GameMap.Cell[land].HasActor())
            return null;

        Actor subject = (Actor)GameMap.Cell[land].Actor;
        if(!subject.IsSlammable)
        {
            Debug.LogError("ActionSlam.GetTargetMove ERROR: Player is landing w/ slam on non-slammable opponent, this is a bug!");
        }

        GridPoint2 slamland = GetLanding(subject, false);

        float time = GetTime(PointyHexPoint.HexNorm(subject.Location - slamland)) * 1.5f;

        Vector3 preSlamMove = 1.2f * (GameMap.Cell[slamland].transform.position - subject.transform.position).normalized;

        TurnAction slamImpactMoment = new CodeAction(() => {
            RenderPipeline.RenderCode(() => subject.transform.position += preSlamMove, 0.002f);
            subject.SendMessage("Slammed", SendMessageOptions.DontRequireReceiver); return ActionResult.SuccessOnlyAffectedSelf; 
        });
        TurnAction stickyFrictionPause = new CodeAction(() => { RenderPipeline.RenderCode(() => {/*System.Threading.Thread.Sleep(100)*/}, 0.11f); return ActionResult.SuccessOnlyAffectedSelf; });
        TurnAction moveSubject = new ActionMove(subject, subject.Location, slamland, time);

        slamImpactMoment.FollowupAction = stickyFrictionPause;
        stickyFrictionPause.FollowupAction = moveSubject;
        return slamImpactMoment;

        //blam.FollowupAction = slamMessage;
        //slamMessage.FollowupAction = moveSubject;
        //return blam;
    }

    private static float GetTime(int dist)
    {
        return (float)dist / 4f;
    }

    private GridPoint2 GetLanding(Actor actor, bool isSlammer)
    {
        GridPoint2 check = actor.Location;

        do
        {
            check = check + direction;
            if (!GameMap.Contains(check))
                return check - direction;

            if (GameMap.Cell[check].HasActor())
            {
                Actor hit = (Actor)GameMap.Cell[check].Actor;
                if (isSlammer && hit.IsSlammable && GameMap.Available(check+direction))
                    return check;
                else
                    return check - direction;
            }

        } while (GameMap.Contains(check));

        Debug.LogError("ActionSlam.GetLanding ran past the end of the check, this is a bug.  Best-guess " + (check-direction));
        return check - direction;
    }
}
