package dev.peerat.backend.repository;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;

import dev.peerat.backend.Configuration;
import dev.peerat.backend.model.Group;
import dev.peerat.backend.model.Player;

public class DatabaseLeaderboardRepository extends BaseDatabaseQuery{
	
	private static enum Query{
		
		// LEADERBOARD
		ALL_PLAYERS_FOR_LEADERBOARD(
				"select p.*, scores.*, g.* from players p ,(SELECT fk_player, SUM(c.score) AS score, COUNT(c.id_completion) AS completions, SUM(c.tries) AS tries, rank() over(ORDER BY score DESC) AS rank FROM completions c LEFT JOIN puzzles puzz on puzz.id_puzzle = c.fk_puzzle LEFT JOIN chapters chap on chap.id_chapter = puzz.fk_chapter WHERE chap.id_chapter > 1 GROUP BY c.fk_player) AS scores LEFT JOIN containsGroups cg ON scores.fk_player = cg.fk_player LEFT JOIN groups g ON cg.fk_group = g.id_group  WHERE p.id_player = scores.fk_player ORDER BY g.fk_chapter"),
		ALL_GROUP_FOR_CHAPTER_LEADERBOARD(
				"SELECT g.*, pl.pseudo, co.score, co.tries FROM groups g LEFT JOIN containsGroups cg ON g.id_group = cg.fk_group LEFT JOIN players pl ON cg.fk_player = pl.id_player LEFT JOIN completions co ON pl.id_player = co.fk_player WHERE cg.fk_player IS NOT NULL AND fk_chapter = ? AND (co.fk_puzzle IN (SELECT id_puzzle FROM puzzles puz WHERE puz.fk_chapter = g.fk_chapter) OR co.score IS NULL);");

		private String request;

		Query(Query parent, String request) {
			this.request = parent.request + request;
		}

		Query(String request) {
			this.request = request;
		}

		public PreparedStatement prepare(BaseDatabaseQuery base) throws SQLException {
			return base.prepare(this.request);
		}

		@Override
		public String toString() {
			return this.request;
		}
	}
	
	private Configuration config;
	
	public DatabaseLeaderboardRepository(ConnectionManager con, Configuration config){
		super(con);
		this.config = config;
	}

	public SortedSet<Player> getAllPlayerForLeaderboard() {
		try {
			ensureConnection();
			PreparedStatement playersStmt = Query.ALL_PLAYERS_FOR_LEADERBOARD.prepare(this);
			ResultSet result = playersStmt.executeQuery();
			ArrayList<Player> players = new ArrayList<Player>();
			Player tmpPlayer;
			while (result.next()) {
				tmpPlayer = makePlayer(result, result.getInt("id_player"));
				if (!players.contains(tmpPlayer)) {
					players.add(tmpPlayer);
				} else {
					players.get(players.indexOf(tmpPlayer)).addGroup(makeGroup(result));
				}
			}
			return new TreeSet<Player>(players);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return null;
	}

	public SortedSet<Group> getAllGroupForChapterLeaderboard(int chapterId){
		try{
			ensureConnection();
			PreparedStatement groupsStmt = Query.ALL_GROUP_FOR_CHAPTER_LEADERBOARD.prepare(this);
			groupsStmt.setInt(1, chapterId);
			ResultSet result = groupsStmt.executeQuery();
			List<Group> groups = new ArrayList<Group>();
			Group tmpGroup;
			while (result.next()) {
				tmpGroup = makeGroup(result);
				if (tmpGroup != null) {
					int gPosition = groups.indexOf(tmpGroup);
					if (gPosition < 0) {
						tmpGroup.addPlayer(makeGroupPlayer(result));
						groups.add(tmpGroup);
					} else {
						groups.get(gPosition).addPlayer(makeGroupPlayer(result));
					}
				}
			}
			return new TreeSet<Group>(groups);
		}catch(SQLException e){
			e.printStackTrace();
		}
		return null;
	}

}
