package cn.citycraft.AuthMe.commands;

import java.security.NoSuchAlgorithmException;

import org.bukkit.Location;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.scheduler.BukkitTask;

import cn.citycraft.AuthMe.AuthMe;
import cn.citycraft.AuthMe.ConsoleLogger;
import cn.citycraft.AuthMe.Utils;
import cn.citycraft.AuthMe.Utils.GroupType;
import cn.citycraft.AuthMe.cache.auth.PlayerCache;
import cn.citycraft.AuthMe.cache.backup.JsonCache;
import cn.citycraft.AuthMe.cache.limbo.LimboCache;
import cn.citycraft.AuthMe.security.PasswordSecurity;
import cn.citycraft.AuthMe.settings.Messages;
import cn.citycraft.AuthMe.settings.Settings;
import cn.citycraft.AuthMe.task.MessageTask;
import cn.citycraft.AuthMe.task.TimeoutTask;
import fr.xephi.authme.events.SpawnTeleportEvent;

public class UnregisterCommand implements CommandExecutor {

	public AuthMe plugin;
	private final Messages m = Messages.getInstance();
	private final JsonCache playerCache;

	public UnregisterCommand(final AuthMe plugin) {
		this.plugin = plugin;
		this.playerCache = new JsonCache();
	}

	@Override
	public boolean onCommand(final CommandSender sender, final Command cmnd, final String label, final String[] args) {
		if (!(sender instanceof Player)) {
			return true;
		}

		if (!plugin.authmePermissible(sender, "authme." + label.toLowerCase())) {
			m.send(sender, "no_perm");
			return true;
		}

		final Player player = (Player) sender;
		final String name = player.getName().toLowerCase();

		if (!PlayerCache.getInstance().isAuthenticated(name)) {
			m.send(player, "not_logged_in");
			return true;
		}

		if (args.length != 1) {
			m.send(player, "usage_unreg");
			return true;
		}
		plugin.getServer().getScheduler().runTaskAsynchronously(plugin, new Runnable() {
			@Override
			public void run() {
				try {
					if (PasswordSecurity.comparePasswordWithHash(args[0], PlayerCache.getInstance().getAuth(name).getHash(), player.getName())) {
						if (!plugin.database.removeAuth(name)) {
							player.sendMessage("error");
							return;
						}
						if (Settings.isForcedRegistrationEnabled) {
							if (Settings.isTeleportToSpawnEnabled && !Settings.noTeleport) {
								final Location spawn = plugin.getSpawnLocation(player);
								final SpawnTeleportEvent tpEvent = new SpawnTeleportEvent(player, player.getLocation(), spawn, false);
								plugin.getServer().getPluginManager().callEvent(tpEvent);
								if (!tpEvent.isCancelled()) {
									player.teleport(tpEvent.getTo());
								}
							}

							player.saveData();
							PlayerCache.getInstance().removePlayer(player.getName().toLowerCase());
							if (!Settings.getRegisteredGroup.isEmpty()) {
								Utils.setGroup(player, GroupType.UNREGISTERED);
							}
							LimboCache.getInstance().addLimboPlayer(player);
							final int delay = Settings.getRegistrationTimeout * 20;
							final int interval = Settings.getWarnMessageInterval;
							final BukkitScheduler sched = sender.getServer().getScheduler();
							if (delay != 0) {
								final BukkitTask id = sched.runTaskLaterAsynchronously(plugin, new TimeoutTask(plugin, name, player), delay);
								LimboCache.getInstance().getLimboPlayer(name).setTimeoutTaskId(id);
							}
							LimboCache.getInstance().getLimboPlayer(name).setMessageTaskId(sched.runTaskAsynchronously(plugin, new MessageTask(plugin, name, m.send("reg_msg"), interval)));
							m.send(player, "unregistered");
							ConsoleLogger.info(player.getDisplayName() + " unregistered himself");
							return;
						}
						if (!Settings.unRegisteredGroup.isEmpty()) {
							Utils.setGroup(player, Utils.GroupType.UNREGISTERED);
						}
						PlayerCache.getInstance().removePlayer(player.getName().toLowerCase());
						// check if Player cache File Exist and delete it, preventing
						// duplication of items
						if (playerCache.doesCacheExist(player)) {
							playerCache.removeCache(player);
						}
						if (Settings.applyBlindEffect) {
							player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, Settings.getRegistrationTimeout * 20, 2));
						}
						if (!Settings.isMovementAllowed && Settings.isRemoveSpeedEnabled) {
							player.setWalkSpeed(0.0f);
							player.setFlySpeed(0.0f);
						}
						m.send(player, "unregistered");
						ConsoleLogger.info(player.getDisplayName() + " unregistered himself");
						if (Settings.isTeleportToSpawnEnabled && !Settings.noTeleport) {
							final Location spawn = plugin.getSpawnLocation(player);
							final SpawnTeleportEvent tpEvent = new SpawnTeleportEvent(player, player.getLocation(), spawn, false);
							plugin.getServer().getPluginManager().callEvent(tpEvent);
							Utils.safeTP(player, spawn);
						}
						return;
					} else {
						m.send(player, "wrong_pwd");
					}
				} catch (final NoSuchAlgorithmException ex) {
					ConsoleLogger.showError(ex.getMessage());
					sender.sendMessage("Internal Error please read the server log");
				}
			}
		});
		return true;
	}
}
