package dev.peerat.backend.routes;

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

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;

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;

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.getChapter(chapterId);

		SortedSet<Group> allGroupsForChapter = databaseRepo.getAllGroupForChapterLeaderboard(chapterId);
		JSONObject leaderboardJSON = new JSONObject();
		if (chInfo.getStartDate() != null)
			leaderboardJSON.put("start_date", chInfo.getStartDate().toString());
		if (chInfo.getEndDate() != null)
			leaderboardJSON.put("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.put("groups", groupsJSON);
		writer.write(leaderboardJSON.toJSONString().replace("\\", ""));
	}

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