package dev.peerat.backend;

import static dev.peerat.framework.RequestType.OPTIONS;

import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;

import dev.peerat.backend.model.PeerAtUser;
import dev.peerat.framework.Context;
import dev.peerat.framework.HttpReader;
import dev.peerat.framework.HttpWriter;
import dev.peerat.framework.Locker;
import dev.peerat.framework.RequestType;
import dev.peerat.framework.Response;
import dev.peerat.framework.Route;
import dev.peerat.framework.Router;
import dev.peerat.mapping.Ship;
import dev.peerat.mapping.providers.mysql.MySQLCompass;
import dev.peerat.mapping.providers.mysql.MySQLMap;
import dev.peerat.framework.Locker.Key;

public class Main{
	public static void main(String[] args) throws Exception{
		Configuration config = new Configuration("config.txt")
			.addDefaultValue("users_files", "/tmp/users_files")
			.load();

		Ship ship = new Ship("mysql", config.getCompass(), new MySQLMap());

		Router<PeerAtUser> router = new Router<PeerAtUser>()
				.configureJwt(
						(builder) -> builder.setExpectedIssuer(config.getTokenIssuer()),
						(claims) -> {
							claims.setIssuer(config.getTokenIssuer()); // who creates the token and signs it
							claims.setExpirationTimeMinutesInTheFuture(config.getTokenExpiration());
						}, 
						(claims) -> new PeerAtUser(claims))
				.activeReOrdering().
				addDefaultHeaders(RequestType.GET, "Access-Control-Allow-Origin: *").
				addDefaultHeaders(RequestType.POST, "Access-Control-Allow-Origin: *").
				addDefaultHeaders(RequestType.OPTIONS,
						"Access-Control-Allow-Origin: *",
						"Access-Control-Allow-Methods: *",
						"Access-Control-Allow-Headers: *");

		router.setDefault((matcher, context, reader, writer) -> {
			context.response(404);
			writer.write("404 not Found.\n");
		});
		
		router.register(new Response(){
			@Route(path = "^(.*)$", type = OPTIONS)
			public void exec(Matcher matcher, Context context, HttpReader reader, HttpWriter writer) throws Exception {
				context.response(200);
			}
		});
		
		initRoutes(router, config);
		
		new Thread(new Runnable(){
			public void run(){
				Key key = new Key();
				
				Locker<Context> locker = router.getLogger();
				
				locker.init(key);
				try {
					while(true){
						locker.lock(key);
						Context instance = locker.getValue(key);
						if(instance == null) continue;
						System.out.println("["+((instance.isLogged()) ? instance.<PeerAtUser>getUser().getPseudo() : "?")+"] "+instance.getType()+" "+instance.getPath()+" -> "+instance.getResponseCode());
					}
				}catch(Exception e){
					e.printStackTrace();
				}
				locker.remove(key);
			}
		}).start();

		if(config.useSsl()) router.configureSSL(config.getSslKeystore(), config.getSslKeystorePasswd());
		router.listen(config.getTcpPort(), config.useSsl());
	}

	private static void initRoutes(Router<PeerAtUser> router, Configuration config) throws Exception{
		Map<String, Integer> playersWaiting = new HashMap<>();
		Mail mail = config.getMail();
		Locker<Group> groupLock = new Locker<>();
		Locker<Completion> leaderboard = new Locker<>();
		
//		Bot bot = new Bot(config, repo, groupLock);
//		bot.start();
	}
}
