import { Client } from "./api/client.js";

import LoginView from "./views/accounts/LoginView.js";
import Dashboard from "./views/Dashboard.js";
import Search from "./views/Search.js";
import HomeView from "./views/HomeView.js";
import RegisterView from "./views/accounts/RegisterView.js";
import LogoutView from "./views/accounts/LogoutView.js";
import GameOfflineView from "./views/GameOfflineView.js";
import GameView from "./views/GameView.js";

import PageNotFoundView from './views/PageNotFoundView.js' 

import AbstractRedirectView from "./views/abstracts/AbstractRedirectView.js";
import MeView from "./views/MeView.js";
import ProfilePageView from "./views/ProfilePageView.js";
import MatchMakingView from "./views/MatchMakingView.js";
import TournamentPageView from "./views/tournament/TournamentPageView.js";
import TournamentsView from "./views/tournament/TournamentsListView.js";
import TournamentCreateView from "./views/tournament/TournamentCreateView.js";

let client = new Client(location.origin);

let lastView = undefined;
let lastPageUrlBeforeLogin = undefined;

const pathToRegex = path => new RegExp("^" + path.replace(/\//g, "\\/").replace(/:\w+/g, "(.+)") + "$");

const getParams = match => {
    const values = match.result.slice(1);
    const keys = Array.from(match.route.path.matchAll(/:(\w+)/g)).map(result => result[1]);

    return Object.fromEntries(keys.map((key, i) => {
        return [key, values[i]];
    }));
};

const navigateTo = async (uri) => {
    if (await router(uri) !== 0)
		return;

	history.pushState(null, null, uri);

	let link = document.querySelector('a[href=\'' + location.pathname + '\']');
	if (link) {
		document.querySelector('[data-link].active')?.classList.remove('active');
		link.classList.add('active');
	}
};

async function renderView(view)
{
    let content = await view.getHtml();
    if (content == null)
        return 1;

    view.setTitle();
    document.querySelector("#app").innerHTML = content

	let error_code = await view.postInit();

    if (error_code === 404)
        renderView(new PageNotFoundView());
    else if (error_code === 403)
        this._client._update_logged(false);
}

const router = async(uri) => {

    const routes = [
        { path: "/", view: Dashboard },
        { path: "/profiles/:username", view: ProfilePageView },
        { path: "/tournaments/create", view: TournamentCreateView },
        { path: "/tournaments/:id", view: TournamentPageView },
        { path: "/tournaments/", view: TournamentsView },
        { path: "/login", view: LoginView },
        { path: "/logout", view: LogoutView },
        { path: "/register", view: RegisterView },
        { path: "/search", view: Search },
        { path: "/home", view: HomeView },
        { path: "/me", view: MeView },
        { path: "/matchmaking", view: MatchMakingView },
        { path: "/games/offline", view: GameOfflineView },
        { path: "/games/:id", view: GameView },
    ];

    // Test each route for potential match
    const potentialMatches = routes.map(route => {
        return {
            route: route,
            result: uri.match(pathToRegex(route.path))
        };
    });

    let match = potentialMatches.find(potentialMatch => potentialMatch.result !== null);

    if (!match) {
        match = {
            route: {
				path: uri,
				view: PageNotFoundView
			},
            result: [uri]
        };
    }

	if (lastView !== undefined)
		await lastView.leavePage();

	if (uri !== '/login' && uri !== '/register' && uri !== '/logout')
		lastPageUrlBeforeLogin = uri;
	else
		lastPageUrlBeforeLogin = undefined;
    const view = new match.route.view(getParams(match), lastPageUrlBeforeLogin);

    if (view instanceof AbstractRedirectView && await view.redirect())
        return 1;

	lastView = view;

    if (await renderView(view))
        return 1;

    return 0;
};

window.addEventListener("popstate", function() {router(location.pathname)});

document.addEventListener("DOMContentLoaded", async () => {
    document.body.addEventListener("click", e => {
        if (e.target.matches("[data-link]")) {
            e.preventDefault();
			if (e.target.classList.contains('nav-link')) {
				document.querySelector('[data-link].active')?.classList.remove('active');
				e.target.classList.add('active');
			}
            navigateTo(e.target.href.slice(location.origin.length));
        }
    });

	//Languages
	Array.from(document.getElementById('languageSelector').children).forEach(el => {
		el.onclick = _ => client.lang.changeLanguage(el.value);
	});

	await client.isAuthentificate();
    router(location.pathname);
	document.querySelector('a[href=\'' + location.pathname + '\']')?.classList.add('active');
});

export { client, navigateTo }
