package com.carrot.carrotshop.listener;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import org.spongepowered.api.block.BlockSnapshot;
import org.spongepowered.api.block.BlockTypes;
import org.spongepowered.api.data.Transaction;
import org.spongepowered.api.data.key.Keys;
import org.spongepowered.api.entity.living.player.Player;
import org.spongepowered.api.event.Listener;
import org.spongepowered.api.event.Order;
import org.spongepowered.api.event.block.ChangeBlockEvent;
import org.spongepowered.api.event.block.tileentity.ChangeSignEvent;
import org.spongepowered.api.util.Direction;
import org.spongepowered.api.world.Location;
import org.spongepowered.api.world.World;

import com.carrot.carrotshop.ShopsData;
import com.carrot.carrotshop.shop.Shop;

public class BlockBreakListener {

	private boolean isSignAndShop(Location<World> loc, Direction dir, boolean wall) {
		if (loc.getRelative(dir).getBlockType() == (wall ? BlockTypes.WALL_SIGN : BlockTypes.STANDING_SIGN)) {
			if (wall) {
				Location<World> sign = loc.getRelative(dir);
				if (sign.supports(Keys.DIRECTION)) {
					Optional<Direction> direction = sign.get(Keys.DIRECTION);
					if (direction.isPresent()) {
						if (direction.get() != dir)
							return false;
					}
				}
			}
			Optional<List<Shop>> shops = ShopsData.getShops(loc.getRelative(dir));
			if (shops.isPresent())
				return true;
		}
		return false;
	}

	@Listener(order = Order.FIRST, beforeModifications = true)
	public void onBlockBreak(ChangeBlockEvent.Break event) {
		for (Transaction<BlockSnapshot> transaction : event.getTransactions()) {
			if (transaction.isValid()) {
				Optional<Location<World>> loc = transaction.getOriginal().getLocation();
				if (loc.isPresent()) {
					Optional<List<Shop>> shops = ShopsData.getShops(loc.get());
					if (shops.isPresent()) {
						Optional<Player> cause = event.getCause().first(Player.class);
						if (!cause.isPresent()) {
							event.setCancelled(true);
						}
						List<Shop> toDelete = new ArrayList<>();
						shops.get().forEach((shop) -> {
							toDelete.add(shop);
						});
						toDelete.forEach((shop) -> {
							if (!shop.destroy(cause.get()))
								event.setCancelled(true);
						});
					} else if (isSignAndShop(loc.get(), Direction.UP, false) ||
							isSignAndShop(loc.get(), Direction.NORTH, true) ||
							isSignAndShop(loc.get(), Direction.SOUTH, true) ||
							isSignAndShop(loc.get(), Direction.EAST, true) ||
							isSignAndShop(loc.get(), Direction.WEST, true)) {
						event.setCancelled(true);
					}
				}
			}
		}
	}

	@Listener(order = Order.FIRST, beforeModifications = true)
	public void onSignChanged(ChangeSignEvent event)
	{
		Optional<List<Shop>> shops = ShopsData.getShops(event.getTargetTile().getLocation());
		if (shops.isPresent()) {
			event.setCancelled(true);
		}
	}
}

@@ -1930,17 +1930,16 @@
 %09%09%09%09if (
-!
 cause.is
@@ -1956,48 +1956,8 @@
  %7B%0A%09
-%09%09%09%09%09%09event.setCancelled(true);%0A%09%09%09%09%09%09%7D%0A
 %09%09%09%09
@@ -2005,16 +2005,17 @@
 ;%0A%09%09%09%09%09%09
+%09
 shops.ge
@@ -2034,24 +2034,25 @@
 (shop) -%3E %7B%0A
+%09
 %09%09%09%09%09%09%09toDel
@@ -2068,28 +2068,30 @@
 hop);%0A%09%09%09%09%09%09
+%09
 %7D);%0A
+%09
 %09%09%09%09%09%09toDele
@@ -2109,24 +2109,25 @@
 (shop) -%3E %7B%0A
+%09
 %09%09%09%09%09%09%09if (!
@@ -2157,24 +2157,25 @@
 )))%0A%09%09%09%09%09%09%09%09
+%09
 event.setCan
@@ -2190,28 +2190,85 @@
 rue);%0A%09%09%09%09%09%09
+%09
 %7D);%0A
+%09%09%09%09%09%09%7D else %7B%0A%09%09%09%09%09%09%09event.setCancelled(true);%0A%09%09%09%09%09%09%7D%0A
 %09%09%09%09%09%7D else 

Fix a trace when shop would have been destroyed by an explosion