package com.elmakers.mine.bukkit.action;

import org.bukkit.Location;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;

import com.elmakers.mine.bukkit.api.action.CastContext;
import com.elmakers.mine.bukkit.api.spell.SpellResult;

public abstract class BaseTeleportAction extends BaseSpellAction
{
    protected int verticalSearchDistance;
    protected boolean safe = true;
    private boolean requiresBuildPermission = false;
    private boolean requiresExitPermission = true;

    @Override
    public void prepare(CastContext context, ConfigurationSection parameters) {
        super.prepare(context, parameters);
        verticalSearchDistance = parameters.getInt("vertical_range", context.getVerticalSearchDistance());
        safe = parameters.getBoolean("safe", true);
        requiresBuildPermission = parameters.getBoolean("require_build", false);
        requiresExitPermission = parameters.getBoolean("require_exit", true);
    }

    protected SpellResult teleport(CastContext context, Entity entity, Location targetLocation) {
        if (requiresBuildPermission && !context.hasBuildPermission(targetLocation.getBlock())) {
            return SpellResult.INSUFFICIENT_PERMISSION;
        }
        if (requiresExitPermission && entity instanceof Player && !context.getController().isExitAllowed((Player)entity, entity.getLocation()) && context.getController().isExitAllowed((Player)entity, targetLocation)) {
            return SpellResult.INSUFFICIENT_PERMISSION;
        }
        if (!context.canCast(targetLocation)) {
            return SpellResult.INSUFFICIENT_PERMISSION;
        }
        return context.teleport(entity, targetLocation, verticalSearchDistance, safe) ? SpellResult.CAST : SpellResult.NO_TARGET;
    }
}

@@ -182,16 +182,47 @@
 .Player;
+%0Aimport org.bukkit.util.Vector;
 %0A%0Aimport
@@ -574,16 +574,58 @@
  = true;
+%0A    private boolean keepVelocity = false;
 %0A%0A    @O
@@ -1070,24 +1070,101 @@
 it%22, true);%0A
+        keepVelocity = parameters.getBoolean(%22keep_velocity%22, keepVelocity);%0A
     %7D%0A%0A    p
@@ -1818,24 +1818,25 @@
       %7D%0A
+%0A
         
 return c
@@ -1827,22 +1827,186 @@
         
-return
+Location sourceLocation = keepVelocity ? entity.getLocation() : null;%0A        Vector sourceVelocity = keepVelocity ? entity.getVelocity() : null;%0A        boolean result =
  context
@@ -2015,16 +2015,33 @@
 eleport(
+%0A                
 entity, 
@@ -2085,16 +2085,726 @@
 e, safe)
+;%0A        if (result && keepVelocity) %7B%0A            // Calculate how much we have rotated%0A            double deltaYaw = targetLocation.getYaw() - sourceLocation.getYaw();%0A            double angle = Math.toRadians(deltaYaw);%0A%0A            // Rotate the original velocity%0A            double cos = Math.cos(angle);%0A            double sin = Math.sin(angle);%0A            double initialX = sourceVelocity.getX();%0A            double initialZ = sourceVelocity.getZ();%0A            sourceVelocity.setX(initialX * cos - initialZ * sin);%0A            sourceVelocity.setZ(initialZ * cos + initialX * sin);%0A%0A            // Re-apply to the entity%0A            entity.setVelocity(sourceVelocity);%0A        %7D%0A%0A        return result
  ? Spell

Add option to maintain velocity when teleporting