package com.loganmagnan.eventcore.managers;

import com.loganmagnan.eventcore.EventCore;
import com.loganmagnan.eventcore.playerdata.PlayerData;
import com.loganmagnan.eventcore.playerdata.PlayerState;
import com.loganmagnan.eventcore.utils.PlayerUtil;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.UpdateOptions;
import lombok.Getter;
import org.bson.Document;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.*;

public class PlayerDataManager {

	private EventCore main = EventCore.getInstance();

	@Getter private Map<UUID, PlayerData> players = new HashMap<>();

	public PlayerData getOrCreate(UUID uniqueId) {
		return this.players.computeIfAbsent(uniqueId, PlayerData::new);
	}

	public PlayerData getPlayerData(UUID uniqueId) {
		return this.players.getOrDefault(uniqueId, new PlayerData(uniqueId));
	}

	public Collection<PlayerData> getAllPlayers() {
		return this.players.values();
	}

	public void loadPlayerData(PlayerData playerData) {
		Document document = this.main.getMongoManager().getPlayers().find(Filters.eq("unique-id", playerData.getUniqueId().toString())).first();

		if (document != null) {
			if (document.getString("chat-color") != null) {
				playerData.setChatColor(ChatColor.valueOf(document.getString("chat-color")));
			}
		}

		playerData.setLoaded(true);
	}

	public void savePlayerData(PlayerData playerData) {
		Document document = new Document();
		document.put("unique-id", playerData.getUniqueId().toString());

		if (playerData.getChatColor() != null) {
			document.put("chat-color", playerData.getChatColor().name());
		}

		this.main.getMongoManager().getPlayers().replaceOne(Filters.eq("unique-id", playerData.getUniqueId().toString()), document, new UpdateOptions().upsert(true));
	}

	public void deletePlayer(UUID uniqueId) {
		this.main.getServer().getScheduler().runTaskAsynchronously(this.main, () -> {
			this.savePlayerData(this.players.get(uniqueId));
			this.players.remove(uniqueId);
		});
	}

	public MongoCursor<Document> getPlayersSorted(String stat) {
		Document sort = new Document();
		sort.put(stat, -1);

		return this.main.getMongoManager().getPlayers().find().sort(sort).limit(10).iterator();
	}

	public void sendToSpawnAndResetPlayer(Player player) {
		this.resetPlayer(player);
		this.giveSpawnItemsToPlayer(player);

		if (!player.isOnline()) {
			return;
		}

		if (this.main.getSpawnManager().getSpawnLocation() != null) {
			player.teleport(this.main.getSpawnManager().getSpawnLocation().toBukkitLocation());
		}
	}

	public void giveSpawnItemsToPlayer(Player player) {
		player.updateInventory();
	}

	public void sendPlayerToSpawn(Player player) {
		if (!player.isOnline()) {
			return;
		}

		if (this.main.getSpawnManager().getSpawnLocation() != null) {
			player.teleport(this.main.getSpawnManager().getSpawnLocation().toBukkitLocation());
		}
	}

	public void resetPlayer(Player player) {
		PlayerData playerData = this.getPlayerData(player.getUniqueId());
		playerData.setPlayerState(PlayerState.SPAWN);

		PlayerUtil.clearPlayer(player);

		this.giveSpawnItemsToPlayer(player);

		if (!player.isOnline()) {
			return;
		}

		this.resetPlayerView();
	}

	public void resetPlayerView() {
		(new BukkitRunnable() {
			public void run() {
				PlayerDataManager.this.main.getServer().getOnlinePlayers().forEach(player -> {
					PlayerData playerData = PlayerDataManager.this.main.getPlayerDataManager().getPlayerData(player.getUniqueId());

					if (playerData.getPlayerSettings().isPlayersEnabled()) {
						PlayerDataManager.this.main.getServer().getOnlinePlayers().forEach(playerOnline -> {
							player.showPlayer(playerOnline);
						});
					} else {
						PlayerDataManager.this.main.getServer().getOnlinePlayers().forEach(playerOnline -> {
							player.hidePlayer(playerOnline);
						});
					}
				});
			}
		}).runTaskAsynchronously(this.main);
	}
}
