'use strict';
import Secure from './secure.js';
import App from './app.js';
import RequestToDomain from './requests-to-domain.js';
// import * as jose from 'jose';  // per la gestione del token

import { getKeycloakRealm, getKeycloakURL, getMyURL } from './configuration.js';


const mySecure = new Secure();

let token = null;
let expirationTime = null; // momento a partire dal quale il token non sarà più valido
let alreadyRefreshed = false; // true se ho appena fatto la richiesta del token usando il refresh token
let oldTimeout = null;
const uri = window.location.toString();

if(!uri.includes(`#`) && !uri.includes("/secured/home/")) {
    const a = document.getElementById("my-link");
    a.href = a.href.replace("$MY_CODE_CHALLENGE", mySecure.codeChallenge).replace("$MY_STATE", mySecure.state);
    sessionStorage.setItem("stateSent", mySecure.state); // state inviato durante la richiesta dell`authcode
    sessionStorage.setItem("codeVerifier", mySecure.codeVerifier);
    //automatically redirect to the login page
    window.location.href = a.href;
}
else if(uri.includes("#")){
    // l`uri e` del tipo localhost:3000/secured# seguito da parametri
    const uriSplit = uri.split(`#`);
    const params = uriSplit[1].split(`&`);
    const uriState = queryStringGetValue(params[0]);
    const uriAuthCode = queryStringGetValue(params[2]);
    if(!sessionStorage.stateSent || sessionStorage.stateSent !== uriState) {
        // get the body element
        const body = document.getElementsByTagName(`body`)[0];
        body.innerHTML =  `Errors in the request!`;
    }
    else {
        await requestFirstToken(uriAuthCode);  // post per la richiesta del token
        if(token !== null) {
            expirationTime = moment().add(token.expires_in,`s`);
            sessionStorage.setItem("expirationTime", expirationTime.toJSON());

            const myDomains = await RequestToDomain.getMyDomains();
// const myDomains = [{nome: "casa1", stato:"on", admin: true},
//                    {nome: "casa2", stato:"off", admin: false},
//                    {nome: "casa3", stato:"off", admin: true},
//                    {nome: "casa4", stato:"on", admin: false},
//                    {nome: "casa4", stato:"on", admin: false},
//                    {nome: "casa4", stato:"on", admin: false},
//                    {nome: "casa4", stato:"on", admin: true},
//                    {nome: "casa4", stato:"on", admin: false}
//                 ];

            const app = new App(myDomains);
        }
    }
} else if(uri.includes(`/secured/home/`)) {
    token = JSON.parse(sessionStorage.getItem(`token`));
    expirationTime = moment(sessionStorage.getItem(`expirationTime`));
    oldTimeout = timeoutRefresh();
}

/**
     * Ottengo il valore associato al parametro.
     * @param {*} queryString query string del tipo parametro=valore.
     * @returns il valore associato al parametro.
     */
function queryStringGetValue(queryString) {
    const arr = queryString.split(`=`);
    return arr[1];
}


/**
 * Post per la richiesta del token;
 *  imposta il token ottenuto
 */
async function requestFirstToken(uriAuthCode) {

    const url = `${getKeycloakURL()}realms/${getKeycloakRealm()}/protocol/openid-connect/token`;
    const response = await fetch(url, {
        method: `POST`,
        headers: {
            'Content-type':`application/x-www-form-urlencoded`
        },
        body: new URLSearchParams({
            grant_type: `authorization_code`,
            client_id: `myclient`,
            code_verifier: sessionStorage.getItem("codeVerifier"),
            code: uriAuthCode,
            redirect_uri: `${getMyURL()}secured`
        })
    });
    token = await response.json();
    if(response.ok) {
        sessionStorage.setItem("token", JSON.stringify(token));
        oldTimeout = timeoutRefresh();
    }
    else
        token = null;
}


async function getToken() {
    const now = moment();
    if(now - expirationTime < 1) {
        //this token has expired, so request new token
        await requestUsingRefreshToken();
    }
    return token.access_token;
}


/**
 * Post per la richiesta del token usando il refresh token.
 */
 async function requestUsingRefreshToken() {
    const url = `${getKeycloakURL()}realms/${getKeycloakRealm()}/protocol/openid-connect/token`;
    const response = await fetch(url, {
        method: `POST`,
        headers: {
            'Content-type':`application/x-www-form-urlencoded`
        },
        body: new URLSearchParams({
            grant_type: `refresh_token`,
            client_id: `myclient`,
            refresh_token: `${token.refresh_token}`
        })
    });
    token = await response.json();
    if(response.ok) {
        alreadyRefreshed = true;
        sessionStorage.setItem("token", JSON.stringify(token));
        expirationTime = moment().add(token.expires_in,`s`);
        sessionStorage.setItem("expirationTime", expirationTime.toJSON());
        oldTimeout = timeoutRefresh();
    }
    else
        token = null;
}


/**
 * Prima che scada il refresh token, richiedo nuovamente il token
 * (usando il refresh token).
 * @returns id di setTimeout()
 */
function timeoutRefresh() {
    if(oldTimeout !== null)
        clearTimeout(oldTimeout);

    return setTimeout(async () => {
        if(!alreadyRefreshed) {
            await requestUsingRefreshToken();
            alreadyRefreshed = false;
        }
    }, 10000);//(token.refresh_expires_in*1000)-5000);
}


/**
 * Effettua il logout.
 */
async function logoutKeycloak() {
    if(token == null)
        return;
    clearTimeout(oldTimeout); // DA FARE: funziona, ma vedere se fare il redirect alla pagina iniziale.
    window.location.href = `${getKeycloakURL()}realms/${getKeycloakRealm()}/protocol/openid-connect/logout?id_token_hint=${await getIdToken()}`;
}


async function getIdToken() {
    const now = moment();
    if(now - expirationTime < 1) {
        //this token has expired, so request new token
        await requestUsingRefreshToken();
    }
    return token.id_token;
}

export {getToken, logoutKeycloak};