package cn.citycraft.AuthMe.process.register;

import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.entity.Player;
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.cache.limbo.LimboCache;
import cn.citycraft.AuthMe.cache.limbo.LimboPlayer;
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.AuthMeTeleportEvent;
import fr.xephi.authme.events.LoginEvent;
import fr.xephi.authme.events.RegisterTeleportEvent;
import fr.xephi.authme.events.RestoreInventoryEvent;

public class ProcessSyncronousPasswordRegister implements Runnable {

	private final Messages m = Messages.getInstance();
	private final AuthMe plugin;
	protected String name;
	protected Player player;

	public ProcessSyncronousPasswordRegister(final Player player, final AuthMe plugin) {
		this.player = player;
		this.name = player.getName().toLowerCase();
		this.plugin = plugin;
	}

	@Override
	public void run() {
		final LimboPlayer limbo = LimboCache.getInstance().getLimboPlayer(name);
		if (limbo != null) {
			player.setGameMode(limbo.getGameMode());
			if (Settings.isTeleportToSpawnEnabled && !Settings.noTeleport) {
				final Location loca = plugin.getSpawnLocation(player);
				final RegisterTeleportEvent tpEvent = new RegisterTeleportEvent(player, loca);
				plugin.getServer().getPluginManager().callEvent(tpEvent);
				if (!tpEvent.isCancelled()) {
					Utils.safeTP(player, tpEvent.getTo());
				}
			}

			if (Settings.protectInventoryBeforeLogInEnabled && plugin.inventoryProtector != null) {
				final RestoreInventoryEvent event = new RestoreInventoryEvent(player);
				Bukkit.getPluginManager().callEvent(event);
				if (!event.isCancelled()) {
					plugin.inventoryProtector.sendInventoryPacket(player);
				}
			}

			limbo.getTimeoutTaskId().cancel();
			limbo.getMessageTaskId().cancel();
			LimboCache.getInstance().deleteLimboPlayer(name);
		}

		if (!Settings.getRegisteredGroup.isEmpty()) {
			Utils.setGroup(player, Utils.GroupType.REGISTERED);
		}
		m.send(player, "registered");
		if (!Settings.getmailAccount.isEmpty()) {
			m.send(player, "add_email");
		}
		if (player.getGameMode() != GameMode.CREATIVE && !Settings.isMovementAllowed) {
			player.setAllowFlight(false);
			player.setFlying(false);
		}
		if (Settings.applyBlindEffect) {
			player.removePotionEffect(PotionEffectType.BLINDNESS);
		}
		if (!Settings.isMovementAllowed && Settings.isRemoveSpeedEnabled) {
			player.setWalkSpeed(0.2f);
			player.setFlySpeed(0.1f);
		}
		// The LoginEvent now fires (as intended) after everything is processed
		plugin.getServer().getPluginManager().callEvent(new LoginEvent(player, true));
		player.saveData();

		if (!Settings.noConsoleSpam) {
			ConsoleLogger.info(player.getName() + " registered " + plugin.getIP(player));
		}

		// Kick Player after Registration is enabled, kick the player
		if (Settings.forceRegKick) {
			player.kickPlayer(m.send("registered")[0]);
			return;
		}

		// Request Login after Registration
		if (Settings.forceRegLogin) {
			forceLogin(player);
			return;
		}

		// Register is finish and player is logged, display welcome message
		if (Settings.useWelcomeMessage) {
			if (Settings.broadcastWelcomeMessage) {
				for (final String s : Settings.welcomeMsg) {
					plugin.getServer().broadcastMessage(plugin.replaceAllInfos(s, player));
				}
			} else {
				for (final String s : Settings.welcomeMsg) {
					player.sendMessage(plugin.replaceAllInfos(s, player));
				}
			}
		}

		// Register is now finish , we can force all commands
		forceCommands();
	}

	protected void forceCommands() {
		for (final String command : Settings.forceRegisterCommands) {
			try {
				player.performCommand(command.replace("%p", player.getName()));
			} catch (final Exception ignored) {
			}
		}
		for (final String command : Settings.forceRegisterCommandsAsConsole) {
			Bukkit.getServer().dispatchCommand(Bukkit.getServer().getConsoleSender(), command.replace("%p", player.getName()));
		}
	}

	protected void forceLogin(final Player player) {
		if (Settings.isTeleportToSpawnEnabled && !Settings.noTeleport) {
			final Location spawnLoc = plugin.getSpawnLocation(player);
			final AuthMeTeleportEvent tpEvent = new AuthMeTeleportEvent(player, spawnLoc);
			plugin.getServer().getPluginManager().callEvent(tpEvent);
			if (!tpEvent.isCancelled()) {
				Utils.safeTP(player, tpEvent.getTo());
			}
		}
		if (LimboCache.getInstance().hasLimboPlayer(name)) {
			LimboCache.getInstance().deleteLimboPlayer(name);
		}
		LimboCache.getInstance().addLimboPlayer(player);
		final int delay = Settings.getRegistrationTimeout * 20;
		final int interval = Settings.getWarnMessageInterval;
		final BukkitScheduler sched = plugin.getServer().getScheduler();
		if (delay != 0) {
			final BukkitTask id = sched.runTaskLaterAsynchronously(plugin, new TimeoutTask(plugin, name, player), delay);
			LimboCache.getInstance().getLimboPlayer(name).setTimeoutTaskId(id);
		}
		final BukkitTask msgT = sched.runTaskAsynchronously(plugin, new MessageTask(plugin, name, m.send("login_msg"), interval));
		LimboCache.getInstance().getLimboPlayer(name).setMessageTaskId(msgT);
		if (player.isInsideVehicle() && player.getVehicle() != null) {
			player.getVehicle().eject();
		}
	}
}
