/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package pw.yumc.Residence.selection;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.Server;
import org.bukkit.entity.Player;

import com.bekvon.bukkit.residence.permissions.PermissionGroup;
import com.bekvon.bukkit.residence.protection.CuboidArea;

import pw.yumc.Residence.ResidenceMain;

/**
 *
 * @author Administrator
 */
public class SelectionManager {
    public static final int MAX_HEIGHT = 255, MIN_HEIGHT = 0;
    protected Map<String, Location> playerLoc1;
    protected Map<String, Location> playerLoc2;
    protected Server server;
    ResidenceMain plugin;

    public SelectionManager(final ResidenceMain plugin) {
        this.plugin = plugin;
        this.server = Bukkit.getServer();
        playerLoc1 = Collections.synchronizedMap(new HashMap<String, Location>());
        playerLoc2 = Collections.synchronizedMap(new HashMap<String, Location>());
    }

    public void bedrock(final Player player, final boolean resadmin) {
        if (hasPlacedBoth(player.getName())) {
            final PermissionGroup group = plugin.getPermissionManager().getGroup(player);
            final int y1 = playerLoc1.get(player.getName()).getBlockY();
            final int y2 = playerLoc2.get(player.getName()).getBlockY();
            if (y1 < y2) {
                int newy = MIN_HEIGHT;
                if (!resadmin) {
                    if (newy < group.getMinHeight()) {
                        newy = group.getMinHeight();
                    }
                    if (y2 - newy > (group.getMaxY() - 1)) {
                        newy = y2 - (group.getMaxY() - 1);
                    }
                }
                playerLoc1.get(player.getName()).setY(newy);
            } else {
                int newy = MIN_HEIGHT;
                if (!resadmin) {
                    if (newy < group.getMinHeight()) {
                        newy = group.getMinHeight();
                    }
                    if (y1 - newy > (group.getMaxY() - 1)) {
                        newy = y1 - (group.getMaxY() - 1);
                    }
                }
                playerLoc2.get(player.getName()).setY(newy);
            }
            player.sendMessage(ChatColor.GREEN + plugin.getLanguage().getPhrase("SelectionBedrock"));
        } else {
            player.sendMessage(ChatColor.RED + plugin.getLanguage().getPhrase("SelectPoints"));
        }
    }

    public void clearSelection(final Player player) {
        playerLoc1.remove(player.getName());
        playerLoc2.remove(player.getName());
    }

    public Location getPlayerLoc1(final String player) {
        return playerLoc1.get(player);
    }

    public Location getPlayerLoc2(final String player) {
        return playerLoc2.get(player);
    }

    public boolean hasPlacedBoth(final String player) {
        return (playerLoc1.containsKey(player) && playerLoc2.containsKey(player));
    }

    public void modify(final Player player, final boolean shift, final int amount) {
        if (!this.hasPlacedBoth(player.getName())) {
            player.sendMessage(ChatColor.RED + plugin.getLanguage().getPhrase("SelectPoints"));
            return;
        }
        final Direction d = this.getDirection(player);
        if (d == null) {
            player.sendMessage(ChatColor.RED + plugin.getLanguage().getPhrase("InvalidDirection"));
        }
        final CuboidArea area = new CuboidArea(playerLoc1.get(player.getName()), playerLoc2.get(player.getName()));
        if (d == Direction.UP) {
            int oldy = area.getHighLoc().getBlockY();
            oldy = oldy + amount;
            if (oldy > MAX_HEIGHT) {
                player.sendMessage(ChatColor.RED + plugin.getLanguage().getPhrase("SelectTooHigh"));
                oldy = MAX_HEIGHT;
            }
            area.getHighLoc().setY(oldy);
            if (shift) {
                int oldy2 = area.getLowLoc().getBlockY();
                oldy2 = oldy2 + amount;
                area.getLowLoc().setY(oldy2);
                player.sendMessage(ChatColor.YELLOW + plugin.getLanguage().getPhrase("Shifting.Up") + "...");
            } else {
                player.sendMessage(ChatColor.YELLOW + plugin.getLanguage().getPhrase("Expanding.Up") + "...");
            }
        }
        if (d == Direction.DOWN) {
            int oldy = area.getLowLoc().getBlockY();
            oldy = oldy - amount;
            if (oldy < MIN_HEIGHT) {
                player.sendMessage(ChatColor.RED + plugin.getLanguage().getPhrase("SelectTooLow"));
                oldy = MIN_HEIGHT;
            }
            area.getLowLoc().setY(oldy);
            if (shift) {
                int oldy2 = area.getHighLoc().getBlockY();
                oldy2 = oldy2 - amount;
                area.getHighLoc().setY(oldy2);
                player.sendMessage(ChatColor.YELLOW + plugin.getLanguage().getPhrase("Shifting.Down") + "...");
            } else {
                player.sendMessage(ChatColor.YELLOW + plugin.getLanguage().getPhrase("Expanding.Down") + "...");
            }
        }
        if (d == Direction.MINUSX) {
            int oldx = area.getLowLoc().getBlockX();
            oldx = oldx - amount;
            area.getLowLoc().setX(oldx);
            if (shift) {
                int oldx2 = area.getHighLoc().getBlockX();
                oldx2 = oldx2 - amount;
                area.getHighLoc().setX(oldx2);
                player.sendMessage(ChatColor.YELLOW + plugin.getLanguage().getPhrase("Shifting") + " -X...");
            } else {
                player.sendMessage(ChatColor.YELLOW + plugin.getLanguage().getPhrase("Expanding") + " -X...");
            }
        }
        if (d == Direction.PLUSX) {
            int oldx = area.getHighLoc().getBlockX();
            oldx = oldx + amount;
            area.getHighLoc().setX(oldx);
            if (shift) {
                int oldx2 = area.getLowLoc().getBlockX();
                oldx2 = oldx2 + amount;
                area.getLowLoc().setX(oldx2);
                player.sendMessage(ChatColor.YELLOW + plugin.getLanguage().getPhrase("Shifting") + " +X...");
            } else {
                player.sendMessage(ChatColor.YELLOW + plugin.getLanguage().getPhrase("Expanding") + " +X...");
            }
        }
        if (d == Direction.MINUSZ) {
            int oldz = area.getLowLoc().getBlockZ();
            oldz = oldz - amount;
            area.getLowLoc().setZ(oldz);
            if (shift) {
                int oldz2 = area.getHighLoc().getBlockZ();
                oldz2 = oldz2 - amount;
                area.getHighLoc().setZ(oldz2);
                player.sendMessage(ChatColor.YELLOW + plugin.getLanguage().getPhrase("Shifting") + " -Z...");
            } else {
                player.sendMessage(ChatColor.YELLOW + plugin.getLanguage().getPhrase("Expanding") + " -Z...");
            }
        }
        if (d == Direction.PLUSZ) {
            int oldz = area.getHighLoc().getBlockZ();
            oldz = oldz + amount;
            area.getHighLoc().setZ(oldz);
            if (shift) {
                int oldz2 = area.getLowLoc().getBlockZ();
                oldz2 = oldz2 + amount;
                area.getLowLoc().setZ(oldz2);
                player.sendMessage(ChatColor.YELLOW + plugin.getLanguage().getPhrase("Shifting") + " +Z...");
            } else {
                player.sendMessage(ChatColor.YELLOW + plugin.getLanguage().getPhrase("Expanding") + " +Z...");
            }
        }
        playerLoc1.put(player.getName(), area.getHighLoc());
        playerLoc2.put(player.getName(), area.getLowLoc());
    }

    public void placeLoc1(final Player player, final Location loc) {
        if (loc != null) {
            playerLoc1.put(player.getName(), loc);
        }
    }

    public void placeLoc2(final Player player, final Location loc) {
        if (loc != null) {
            playerLoc2.put(player.getName(), loc);
        }
    }

    public void selectBySize(final Player player, final int xsize, final int ysize, final int zsize) {
        final Location myloc = player.getLocation();
        final Location loc1 = new Location(myloc.getWorld(), myloc.getBlockX() + xsize, myloc.getBlockY() + ysize, myloc.getBlockZ() + zsize);
        final Location loc2 = new Location(myloc.getWorld(), myloc.getBlockX() - xsize, myloc.getBlockY() - ysize, myloc.getBlockZ() - zsize);
        placeLoc1(player, loc1);
        placeLoc2(player, loc2);
        player.sendMessage(ChatColor.GREEN + plugin.getLanguage().getPhrase("SelectionSuccess"));
        showSelectionInfo(player);
    }

    public void selectChunk(final Player player) {
        final Chunk chunk = player.getWorld().getChunkAt(player.getLocation());
        final int xcoord = chunk.getX() * 16;
        final int zcoord = chunk.getZ() * 16;
        final int ycoord = MIN_HEIGHT;
        final int xmax = xcoord + 15;
        final int zmax = zcoord + 15;
        final int ymax = MAX_HEIGHT;
        this.playerLoc1.put(player.getName(), new Location(player.getWorld(), xcoord, ycoord, zcoord));
        this.playerLoc2.put(player.getName(), new Location(player.getWorld(), xmax, ymax, zmax));
        player.sendMessage(ChatColor.GREEN + plugin.getLanguage().getPhrase("SelectionSuccess"));
    }

    public void showSelectionInfo(final Player player) {
        final String pname = player.getName();
        if (this.hasPlacedBoth(pname)) {
            final CuboidArea cuboidArea = new CuboidArea(getPlayerLoc1(pname), getPlayerLoc2(pname));
            player.sendMessage(ChatColor.YELLOW + plugin.getLanguage().getPhrase("Selection.Total.Size") + ":" + ChatColor.DARK_AQUA + " " + cuboidArea.getSize());
            final PermissionGroup group = plugin.getPermissionManager().getGroup(player);
            if (plugin.getConfigManager().enableEconomy()) {
                player.sendMessage(
                        ChatColor.YELLOW + plugin.getLanguage().getPhrase("Land.Cost") + ":" + ChatColor.DARK_AQUA + " " + ((int) Math.ceil(cuboidArea.getSize() * group.getCostPerBlock())));
            }
            player.sendMessage(ChatColor.YELLOW + "X" + plugin.getLanguage().getPhrase("Size") + ":" + ChatColor.DARK_AQUA + " " + cuboidArea.getXSize());
            player.sendMessage(ChatColor.YELLOW + "Y" + plugin.getLanguage().getPhrase("Size") + ":" + ChatColor.DARK_AQUA + " " + cuboidArea.getYSize());
            player.sendMessage(ChatColor.YELLOW + "Z" + plugin.getLanguage().getPhrase("Size") + ":" + ChatColor.DARK_AQUA + " " + cuboidArea.getZSize());
        } else {
            player.sendMessage(ChatColor.RED + plugin.getLanguage().getPhrase("SelectPoints"));
        }
    }

    public void sky(final Player player, final boolean resadmin) {
        if (hasPlacedBoth(player.getName())) {
            final PermissionGroup group = plugin.getPermissionManager().getGroup(player);
            final int y1 = playerLoc1.get(player.getName()).getBlockY();
            final int y2 = playerLoc2.get(player.getName()).getBlockY();
            if (y1 > y2) {
                int newy = MAX_HEIGHT;
                if (!resadmin) {
                    if (group.getMaxHeight() < newy) {
                        newy = group.getMaxHeight();
                    }
                    if (newy - y2 > (group.getMaxY() - 1)) {
                        newy = y2 + (group.getMaxY() - 1);
                    }
                }
                playerLoc1.get(player.getName()).setY(newy);
            } else {
                int newy = MAX_HEIGHT;
                if (!resadmin) {
                    if (group.getMaxHeight() < newy) {
                        newy = group.getMaxHeight();
                    }
                    if (newy - y1 > (group.getMaxY() - 1)) {
                        newy = y1 + (group.getMaxY() - 1);
                    }
                }
                playerLoc2.get(player.getName()).setY(newy);
            }
            player.sendMessage(ChatColor.GREEN + plugin.getLanguage().getPhrase("SelectionSky"));
        } else {
            player.sendMessage(ChatColor.RED + plugin.getLanguage().getPhrase("SelectPoints"));
        }
    }

    public void vert(final Player player, final boolean resadmin) {
        if (hasPlacedBoth(player.getName())) {
            this.sky(player, resadmin);
            this.bedrock(player, resadmin);
        } else {
            player.sendMessage(ChatColor.RED + plugin.getLanguage().getPhrase("SelectPoints"));
        }
    }

    public boolean worldEdit(final Player player) {
        player.sendMessage(ChatColor.RED + plugin.getLanguage().getPhrase("WorldEditNotFound"));
        return false;
    }

    private Direction getDirection(final Player player) {
        final float pitch = player.getLocation().getPitch();
        final float yaw = player.getLocation().getYaw();
        if (pitch < -50) {
            return Direction.UP;
        }
        if (pitch > 50) {
            return Direction.DOWN;
        }
        if ((yaw > 45 && yaw < 135) || (yaw < -45 && yaw > -135)) {
            return Direction.MINUSX;
        }
        if ((yaw > 225 && yaw < 315) || (yaw < -225 && yaw > -315)) {
            return Direction.PLUSX;
        }
        if ((yaw > 135 && yaw < 225) || (yaw < -135 && yaw > -225)) {
            return Direction.MINUSZ;
        }
        if ((yaw < 45 || yaw > 315) || (yaw > -45 || yaw < -315)) {
            return Direction.PLUSZ;
        }
        return null;
    }

    public enum Direction {
        DOWN,
        MINUSX,
        MINUSZ,
        PLUSX,
        PLUSZ,
        UP
    }

}
