package pl.islandworld.managers;

import java.io.File;
import java.io.IOException;
import java.util.UUID;

import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import org.bukkit.metadata.FixedMetadataValue;
import org.primesoft.asyncworldedit.AsyncWorldEditMain;
import org.primesoft.asyncworldedit.api.IAsyncWorldEdit;
import org.primesoft.asyncworldedit.api.blockPlacer.IBlockPlacer;
import org.primesoft.asyncworldedit.api.blockPlacer.IBlockPlacerListener;
import org.primesoft.asyncworldedit.api.blockPlacer.IJobEntryListener;
import org.primesoft.asyncworldedit.blockPlacer.entries.JobEntry;
import org.primesoft.asyncworldedit.configuration.PermissionGroup;
import org.primesoft.asyncworldedit.playerManager.PlayerEntry;
import org.primesoft.asyncworldedit.utils.FuncParamEx;
import org.primesoft.asyncworldedit.worldedit.AsyncEditSessionFactory;
import org.primesoft.asyncworldedit.worldedit.CancelabeEditSession;
import org.primesoft.asyncworldedit.worldedit.ThreadSafeEditSession;

import com.sk89q.worldedit.CuboidClipboard;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.bukkit.BukkitWorld;
import com.sk89q.worldedit.schematic.SchematicFormat;
import com.sk89q.worldedit.world.DataException;

import pl.islandworld.Config;
import pl.islandworld.IslandWorld;
import pl.islandworld.entity.SimpleIsland;
/**
 * 
 * @author Gnacik
 * 
 */

@SuppressWarnings("deprecation")
public class AsyncSchematicManager extends SchematicManager
{
	private static IslandWorld plugin;
	private boolean listening = false;
	private UUID uid = UUID.fromString("11111111-1111-1111-1111-111111111111");     

	public AsyncSchematicManager(IslandWorld plug)
	{
		plugin = plug;
	}
	
	public void pasteSchematic(final File file, Location origin, Player player)
	{
		final Vector v = new Vector(origin.getBlockX(), origin.getBlockY(), origin.getBlockZ());

		final AsyncWorldEditMain aweMain = (AsyncWorldEditMain)Bukkit.getPluginManager().getPlugin("AsyncWorldEdit");
        final IAsyncWorldEdit aweAPI = aweMain.getAPI();
        final IBlockPlacer bPlacer = aweAPI.getBlockPlacer();
		final AsyncEditSessionFactory factory = (AsyncEditSessionFactory)WorldEdit.getInstance().getEditSessionFactory();
		final PlayerEntry pe = new PlayerEntry(player.getName(), uid);
		final ConfigurationSection cfg = plugin.getConfig().getConfigurationSection("awe-group");
		final PermissionGroup pg = new PermissionGroup(cfg, true);
		
		pe.update(player, pg);
		
		final ThreadSafeEditSession es = factory.getThreadSafeEditSession(new BukkitWorld(plugin.getIslandWorld()), 999999999, null, pe);  
		
        final IJobEntryListener stateListener = new IJobEntryListener()
        {
            @Override
            public void jobStateChanged(JobEntry job) 
            {
                PlayerEntry pEntry = job.getPlayer();
                String name = job.getName();
                plugin.debug("State: " + name + " " + pEntry.getName() + " " + pEntry.getUUID().toString() + "  " + job.getStatus() + " " + job.isTaskDone());
            }
        };
        
        final IBlockPlacerListener listener = new IBlockPlacerListener() 
        {
        	@Override
            public void jobAdded(JobEntry job)
        	{
                PlayerEntry pEntry = job.getPlayer();
                String name = job.getName();

        		job.addStateChangedListener(stateListener);

        		plugin.debug("JobAdded: " + name + " " + pEntry.getName() + " " + pEntry.getUUID().toString() + "  " + job.getStatus() + " " + job.isTaskDone());
        	}

            @Override
            public void jobRemoved(JobEntry job)
            {
                PlayerEntry pEntry = job.getPlayer();
                String name = job.getName();

                job.addStateChangedListener(stateListener);
                
                if (job.isTaskDone() && name.equalsIgnoreCase("IslandPaste") && pEntry.getUUID().equals(uid))
                	afterPaste(pEntry.getName());

                plugin.debug("JobRemoved: " + name + " " + pEntry.getName() + " " + pEntry.getUUID().toString() + "  " + job.getStatus() + " " + job.isTaskDone());
            }
        };

        if (!listening)
        {
        	bPlacer.addListener(listener);
        	
        	listening = true;
        }

       	bPlacer.performAsAsyncJob(es, pe, "IslandPaste", 
       	        new FuncParamEx<Integer, CancelabeEditSession, MaxChangedBlocksException>()
       	        {
					@Override
       				public Integer execute(CancelabeEditSession arg0) throws MaxChangedBlocksException
       				{
						CuboidClipboard cc;
						SchematicFormat schematic = SchematicFormat.getFormat(file);
       			        try
       					{
       			        	cc = schematic.load(file);
       			        	cc.setOffset(new Vector(0, 0, 0));
       			        	cc.paste(arg0, v, false);
       					}
       					catch (IOException e)
       					{
       						e.printStackTrace();
       					}
       					catch (DataException e)
       					{
       						e.printStackTrace();
       					}
       					catch (MaxChangedBlocksException e)
       					{
       						e.printStackTrace();
       					}
       			        
       					return 0;
       				}
       	       	}
       	);
        
	}
	
	public void pasteSchematic(Player player, SimpleIsland island, String sName)
	{
		final World world = plugin.getIslandWorld();
		if (player == null || world == null)
			return;

		// Generate it
		int x = (island.getX() * Config.ISLE_SIZE) + (Config.ISLE_SIZE / 2);
		int y = Config.ISLE_HEIGHT - 1;
		int z = (island.getZ() * Config.ISLE_SIZE) + (Config.ISLE_SIZE / 2);

		plugin.debug("Starting schematic '"+sName+"' paste");

		File schemaFile = new File(plugin.getDataFolder() + "/schematics/" + sName + ".schematic");

		plugin.debug("File: " + schemaFile.toString());

		Location loc = new Location(world, x, y, z);

		plugin.debug("Paste at: " + loc.toString());

		player.setMetadata("schematic", new FixedMetadataValue(plugin, sName));
		
		pasteSchematic(schemaFile, loc, player);
	}
	
	public void afterPaste(String pName)
	{
		final Player player = Bukkit.getPlayer(pName);
		if(player == null)
		{
			plugin.debug("afterPaste player null");
			return;
		}
		
		final SimpleIsland island = plugin.getPlayerIsland(player);
		if(island == null)
		{
			plugin.debug("afterPaste island null");
			return;
		}
		
		String sName = player.getMetadata("schematic").get(0).asString();
		if (sName == null || sName.isEmpty())
			sName = "normal";
		
		Bukkit.getScheduler().runTaskLater(plugin, new callAfterPaste(island, player, sName), plugin.getConfig().getInt("after-paste-delay", 0));
		
		return;
	}
	
	public class callAfterPaste implements Runnable
	{
		private SimpleIsland _isle;
		private Player _player;
		private String _schem;
		
		public callAfterPaste(SimpleIsland isle, Player player, String schem)
		{
			_isle = isle;
			_player = player;
			_schem = schem;
		}
		
		@Override
		public void run()
		{
			plugin.afterPaste(_isle, _player, _schem);
		}
	}
}