package com.publicuhc.scatter.logic;

import com.publicuhc.scatter.ScatterParameters;
import com.publicuhc.scatter.exceptions.ScatterConfigurationException;
import com.publicuhc.scatter.exceptions.ScatterLocationException;
import com.publicuhc.scatter.zones.DeadZone;
import org.bukkit.Location;

import java.util.List;
import java.util.Random;

public abstract class ScatterLogic {

    private final Random m_random;

    public static final double X_CENTRE = 0.5D;
    public static final double Z_CENTRE = 0.5D;

    public ScatterLogic(Random random) {
        m_random = random;
    }

    public Random getRandom() {
        return m_random;
    }

    /**
     * Gets the Z distance from the radius and angle
     * @param radius the radius
     * @param angle the angle
     * @return the Z distance
     */
    public static double getZFromRadians(double radius, double angle) {
        return radius * StrictMath.sin(angle);
    }

    /**
     * Gets the X distance from the radius and angle
     * @param radius the radius
     * @param angle the angle
     * @return the X distance
     */
    public static double getXFromRadians(double radius, double angle) {
        return radius * StrictMath.cos(angle);
    }

    /**
     * Sets the X and Z values to the nearest centre of a block (0.5,0.5)
     * @param location the location to set
     */
    public static void setToNearestCentre(Location location) {
        location.setX(Math.floor(location.getX()) + X_CENTRE);
        location.setZ(Math.floor(location.getZ()) + Z_CENTRE);
    }

    /**
     * Get a list of valid scatter locations
     * @param deadZones the list of zones for which spawning should be disallowed
     * @return a valid location
     * @throws com.publicuhc.scatter.exceptions.ScatterLocationException on being not able to get a valid location
     * @throws com.publicuhc.scatter.exceptions.ScatterConfigurationException if needed parameters in ScatterParameters are missing
     */
    public abstract List<Location> getScatterLocation(List<DeadZone> deadZones, ScatterParameters parameters) throws ScatterLocationException, ScatterConfigurationException;

    /**
     * @return the unique name of the scatter logic
     */
    public abstract String getID();

    /**
     * @return a short description of how we scatter
     */
    public abstract String getDescription();
}

@@ -79,16 +79,79 @@
 meters;%0A
+import com.publicuhc.scatter.exceptions.NoSolidBlockException;%0A
 import c
@@ -205,32 +205,32 @@
 ationException;%0A
-
 import com.publi
@@ -351,16 +351,110 @@
 ocation;
+%0Aimport org.bukkit.Material;%0Aimport org.bukkit.block.Block;%0Aimport org.bukkit.block.BlockFace;
 %0A%0Aimport
@@ -1635,24 +1635,24 @@
  X_CENTRE);%0A
-
         loca
@@ -1701,32 +1701,995 @@
 CENTRE);%0A    %7D%0A%0A
+    /**%0A     * Sets the Y coordinate to the highest non air block at a location, starting at it's Y and moving down%0A     *%0A     * @param loc The location to use%0A     * @throws com.publicuhc.scatter.exceptions.NoSolidBlockException when there was no valid block found%0A     */%0A    public static void setToHighestNonAir(Location loc) throws NoSolidBlockException %7B%0A        //Load the chunk first so the world is generated%0A        if (!loc.getChunk().isLoaded()) %7B%0A            loc.getChunk().load(true);%0A        %7D%0A%0A        Block block = loc.getBlock();%0A        while(block != null) %7B%0A            //set the Y if we find a non-air block%0A            if(block.getType() != Material.AIR) %7B%0A                loc.setY(block.getY());%0A                return;%0A            %7D%0A            //keep falling down%0A            block = block.getRelative(BlockFace.DOWN);%0A        %7D%0A%0A        //no non-air blocks were found all the way down%0A        throw new NoSolidBlockException();%0A    %7D%0A%0A
     /**%0A     * G

add a utility function to set the Y to the highest non air block from the given Y location down