import { WebRest } from 'arm-common';
import { setRestContainer as setQBRestContainer } from 'arm-core-querybuilder';
import { setRestContainer as setSPRestContainer } from 'arm-gui-grid-wj';

import SessionWorkerManager from '../SessionWorkerManager.js';
import AppActions, { EnumNotifyType } from '../app/AppActions.js';
import { AppConstants } from '../constants/AppConstants.js';
import { store } from '../reducers/store.js';
import AccountActions from '../ui/account/AccountActions.js';


/**
 * @param {number} minutes 
 * @returns {number} minutes in milliseconds
 */
function getMinutesInMilliseconds(minutes){
    return 1000 * 60 * minutes;
}

function onSessionExpired() {
    const dispatch = store.dispatch;
    dispatch(AccountActions.logoutExpiredSession());
}

/**
 * classe Rest basata su WebRest
 */
class Rest extends WebRest {
    constructor() {
        /** @type {import('arm-common').SessionConfigOptions} */
        const sessionConf = {};
        if (window.Worker){
            SessionWorkerManager.setSessionExpiredTimeout(getMinutesInMilliseconds(AppConstants.SESSION_EXPIRED_TIMEOUT));
            SessionWorkerManager.setExpireFunction(onSessionExpired);
            sessionConf.externalSessionTimeoutHandler = SessionWorkerManager.clear.bind(SessionWorkerManager);
        } else {
            sessionConf.sessionExpiredHandlerTimeout = AppConstants.SESSION_EXPIRED_TIMEOUT;
            sessionConf.sessionExpiredHandler = onSessionExpired;
        }

        super(
            AppConstants.REST_SERVER, //
            AppConstants.REST_BASE_URL, //
            ["account/login", "authentication/loginbo"], // to skip

            // recover jsessionId
            () => {
                let app = store.getState().app;
                return app.jsessionId;
            },

            // loading, show loader
            (dispatch) => dispatch(AppActions.showLoader()),

            // end load, hide loader
            (dispatch) => dispatch(AppActions.hideLoader()),

            // handle error message
            (dispatch, message, statusCode, options, stacktrace) => AppActions.addNotify(EnumNotifyType.Danger, message),

            // do logout
            (dispatch) => dispatch({ type: 'LOGOUT' }),

            // path iniziale per chiamate stubs
            "./stubs/",

            // recover serverId
            () => {
                let app = store.getState().app;
                return app.serverid;
            },
            sessionConf, // Sessionconf
            "cid", // default JBOSS string identifier for conversation id
            {
                useRequestId: true,
                base64: true,
                zip: true,
                minKbToZip: 500
            } // attiva encoding in base64 del body delle post.
        )

        setQBRestContainer(this);
        setSPRestContainer(this);
    }

    qs(fields) {
        let q = "";
        let sep = "?";
        Object.keys(fields || {}).forEach((k) => {
            let v = fields[k];
            if (v === null || v === undefined) return;
            v = encodeURIComponent(v);
            q += sep + k + "=" + v;
            sep = "&";
        });

        return q;
    }

    parseQueryString(queryString) {
        const queryStringTruncated = queryString.substring(queryString.indexOf('?') + 1);
        const unparsedParams = queryStringTruncated.split('&');
        const params = {};
        unparsedParams.forEach((param) => {
            const [key, value] = param.split('=');
            params[key] = decodeURIComponent(value);
        });
        return params;
    }
    
    saveByteArray(fileName, resultByte, mimeType) {
        if (!resultByte) return;
        const bytes = new Uint8Array(resultByte); // pass your byte response to this constructor
        const blob = new Blob([bytes], { type: mimeType });
        const link = document.createElement('a');
        link.href = window.URL.createObjectURL(blob);
        link.download = fileName;
        link.click();
        link.remove();
    }

    base64ToBlob(base64, type = "application/octet-stream") {
        const binStr = atob(base64);
        const len = binStr.length;
        const arr = new Uint8Array(len);
        for (let i = 0; i < len; i++) {
            arr[i] = binStr.charCodeAt(i);
        }
        return new Blob([arr], { type: type });
    }
}

export default new Rest;