package dev.peerat.backend.routes;

import java.io.IOException;
import java.util.SortedSet;
import java.util.regex.Matcher;

import dev.peerat.backend.bonus.extract.RouteDoc;
import dev.peerat.backend.model.Chapter;
import dev.peerat.backend.model.Group;
import dev.peerat.backend.model.Player;
import dev.peerat.backend.repository.DatabaseRepository;
import dev.peerat.framework.Context;
import dev.peerat.framework.HttpReader;
import dev.peerat.framework.HttpWriter;
import dev.peerat.framework.Response;
import dev.peerat.framework.Route;
import dev.peerat.framework.utils.json.JsonArray;
import dev.peerat.framework.utils.json.JsonMap;

public class Leaderboard implements Response {

	private final DatabaseRepository databaseRepo;

	public Leaderboard(DatabaseRepository databaseRepo) {
		this.databaseRepo = databaseRepo;
	}
	
	@RouteDoc(path = "/leaderboard/{id}", responseCode = 200, responseDescription = "JSON contenant le leaderboard")

	@Route(path = "^\\/leaderboard\\/?(\\d+)?$")
	public void exec(Matcher matcher, Context context, HttpReader reader, HttpWriter writer) throws Exception {
		context.response(200);
		if (matcher.group(1) != null) {
			groupsLeaderboard(Integer.parseInt(matcher.group(1)), writer);
		} else {
			playersLeaderboard(writer);
		}
	}

	public final void groupsLeaderboard(int chapterId, HttpWriter writer) throws IOException {
		Chapter chInfo = databaseRepo.getChapterRepository().getChapter(chapterId);

		SortedSet<Group> allGroupsForChapter = databaseRepo.getLeaderboardRepository().getAllGroupForChapterLeaderboard(chapterId);
		JsonMap leaderboardJSON = new JsonMap();
		if (chInfo.getStartDate() != null)
			leaderboardJSON.set("start_date", chInfo.getStartDate().toString());
		if (chInfo.getEndDate() != null)
			leaderboardJSON.set("end_date", chInfo.getEndDate().toString());
		JsonArray groupsJSON = new JsonArray();
		if (allGroupsForChapter != null) {
			int rank = 1;
			int sameRankCount = 1;
			Group previousGroup = null;
			for (Group g : allGroupsForChapter) {
				if (previousGroup != null) {
					if (g.compareTo(previousGroup) == 0) {
						sameRankCount++;
					} else {
						rank = rank + sameRankCount;
						sameRankCount = 1;
					}
				}
				groupsJSON.add(g.toJson(rank));
				previousGroup = g;
			}
		}
		leaderboardJSON.set("groups", groupsJSON);
		writer.write(leaderboardJSON.toString());
	}

	public final void playersLeaderboard(HttpWriter writer) throws IOException {
		SortedSet<Player> allPlayers = databaseRepo.getLeaderboardRepository().getAllPlayerForLeaderboard();
		JsonArray playersJSON = new JsonArray();
		if (allPlayers != null) {
			for (Player player : allPlayers) {
				JsonMap playerJSON = new JsonMap();
				playerJSON.set("pseudo", player.getPseudo());
				if (player.getGroups() != null)
					playerJSON.set("groups", player.getJsonGroups());
//				if (player.getAvatar() != null)
//					playerJSON.put("avatar", Base64.getEncoder().encodeToString(player.getAvatar()));
				playerJSON.set("rank", player.getRank());
				playerJSON.set("score", player.getTotalScore());
				playerJSON.set("completions", player.getTotalCompletion());
				playerJSON.set("tries", player.getTotalTries());
				playersJSON.add(playerJSON);
			}
		}
		writer.write(playersJSON.toString());
	}
}
