package com.elmakers.mine.bukkit.magic;

import com.elmakers.mine.bukkit.api.action.CastContext;
import com.elmakers.mine.bukkit.api.magic.Mage;
import de.slikey.effectlib.util.MathUtils;
import org.bukkit.Location;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.util.Vector;

public class SourceLocation {
    private boolean useWandLocation = true;
    private boolean useCastLocation = true;
    private boolean useEyeLocation = false;
    private boolean useTargetLocation = true;
    private boolean useCache = false;

    private Location location;

    public SourceLocation(ConfigurationSection configuration, boolean useCache) {
        this(configuration);
        this.useCache = true;
    }

    public SourceLocation(ConfigurationSection configuration) {
        // This is here for backwards-compatibility
        useWandLocation = configuration.getBoolean("use_wand_location", true);
        if (!useWandLocation) {
            useEyeLocation = true;
            useCastLocation = false;
        }

        useCastLocation = configuration.getBoolean("use_cast_location", useCastLocation);
        useEyeLocation = configuration.getBoolean("use_eye_location", useEyeLocation);

        if (configuration.getBoolean("use_foot_location", false)) {
            useEyeLocation = false;
            useCastLocation = false;
            useWandLocation = false;
        }
        useTargetLocation = configuration.getBoolean("use_target_location", true);

        // This is a special-case here for CustomProjectile
        if (configuration.getBoolean("reorient", false)) {
            useTargetLocation = false;
        }
    }

    public Location getLocation(CastContext context) {
        if (!useCache) {
            location = null;
        } else if (location != null) {
            return location;
        }
        Mage mage = context.getMage();
        boolean useWand = mage != null && useWandLocation;
        boolean useCast = mage != null && useCastLocation;

        // Order is important here, given how we interpret defaults in the constructor
        if (useEyeLocation) {
            location = context.getEyeLocation();
        }
        if (location == null && useCast) {
            location = context.getCastLocation();
        }
        if (location == null && useWand) {
            location = context.getWandLocation();
        }
        if (location == null) {
            location = context.getLocation();
        }
        Location targetLocation = context.getTargetLocation();
        if (useTargetLocation && targetLocation != null) {
            Vector direction = targetLocation.toVector().subtract(location.toVector()).normalize();
            if (MathUtils.isFinite(direction.getX()) && MathUtils.isFinite(direction.getY()) && MathUtils.isFinite(direction.getZ())) {
                location.setDirection(direction);
            }
        }
        return location;
    }

    public void setLocation(Location location) {
        this.location = location;
    }

    public boolean shouldUseWandLocation() {
        return useWandLocation;
    }

    public boolean shouldUseCastLocation() {
        return useCastLocation;
    }

    public boolean shouldUseEyeLocation() {
        return useEyeLocation;
    }
}

@@ -542,16 +542,110 @@
 false;%0A%0A
+    private enum LocationType %7B%0A        CAST,%0A        EYES,%0A        FEET,%0A        WAND%0A    %7D%0A%0A
     priv
@@ -1303,25 +1303,24 @@
 ation);%0A
-%0A
         
 if (conf
@@ -1303,36 +1303,52 @@
 ation);%0A        
-if (
+useTargetLocation = 
 configuration.ge
@@ -1365,34 +1365,341 @@
 use_
-foot_location%22, false)) %7B%0A
+target_location%22, true);%0A%0A        // The new format overrides any of the old ones%0A        String locationTypeString = configuration.getString(%22source_location%22, %22%22);%0A        if (!locationTypeString.isEmpty()) %7B%0A            try %7B%0A                LocationType locationType = LocationType.valueOf(locationTypeString.toUpperCase());%0A    
     
@@ -1722,32 +1722,36 @@
 cation = false;%0A
+    
             useC
@@ -1775,32 +1775,36 @@
 se;%0A            
+ 
+   
 useWandLocation 
@@ -1824,92 +1824,651 @@
     
-%7D%0A        useTargetLocation = configuration.getBoolean(%22use_target_location%22, true);
+        switch (locationType) %7B%0A                    case CAST:%0A                        useCastLocation = true;%0A                        break;%0A                    case WAND:%0A                        useWandLocation = true;%0A                        break;%0A                    case EYES:%0A                        useEyeLocation = true;%0A                        break;%0A                    case FEET:%0A                        break;%0A                %7D%0A            %7D catch (Exception ex) %7B%0A                org.bukkit.Bukkit.getLogger().warning(%22Invalid location type specified in source_location parameter: %22 + locationTypeString);%0A            %7D%0A        %7D
 %0A%0A  

Add source_location property, replaces the old use_*_location ones. One day I should do this for target locations too.