/**
 * Licensed Materials - Property of IBM
 * IBM Cognos Products: Glass
 * (C) Copyright IBM Corp. 2020, 2022
 * US Government Users Restricted Rights - Use, duplication or disclosure
 * restricted by GSA ADP Schedule Contract with IBM Corp.
 */
import StringResources from "caglass/nls/StringResources";
import UrlUtils from "baglass/core-client/js/core-client/utils/UrlUtils";
import BrowserUtils from "baglass/core-client/js/core-client/utils/BrowserUtils";

import CoreUtils from "baglass/core-client/js/core-client/utils/Utils";

export enum SecondaryLoginConstants {
    path = "/login",
    parameters = "secondaryLogin=true",
    successMessageKey = "secondaryLoginSuccess",
    refreshMessageKey = "secondaryLoginRefresh"
}

const LOGIN_PATH = `${SecondaryLoginConstants.path}?${SecondaryLoginConstants.parameters}`;

function showSuccessToast(glassContext: any): void {
    const callback = (e: any): void => {
        if (e.btn === "ok") {
            setTimeout(() => {
                glassContext.close().then(() => {
                    CoreUtils.getCurrentWindow().location.reload();
                });
            }, 1);
        }
    };
    glassContext.appController.showMessage(
        StringResources.get(SecondaryLoginConstants.successMessageKey),
        StringResources.get(SecondaryLoginConstants.refreshMessageKey),
        "info",
        ["ok", "cancel"],
        "500px",
        callback,
        true,
        "ANSDialog"
    );
}

function addMessageListener(
    loginWindow: Window,
    glassContext: any,
    resolve: Function
): void {
    const eventListener = (event: any): void => {
        if (loginWindow && event.source === loginWindow) {
            resolve(event.data);
            loginWindow.close();
            showSuccessToast(glassContext);
            window.removeEventListener("message", eventListener);
        }
    };
    window.addEventListener("message", eventListener, {
        once: true
    });
}

function addStorageListener(
    loginWindow: Window,
    glassContext: any,
    resolve: Function
): void {
    const storageEventHandler = (event: any): void => {
        let secondaryLoginResult;
        if (event.key && event.key === "secondaryLoginResult") {
            secondaryLoginResult = event.newValue;
        }
        if (secondaryLoginResult && loginWindow) {
            window.removeEventListener("storage", storageEventHandler);
            window.localStorage.removeItem("secondaryLoginResult");
            const data = JSON.parse(secondaryLoginResult);
            resolve(data);
            loginWindow.close();
            showSuccessToast(glassContext);
        }
    };
    window.addEventListener("storage", storageEventHandler);
}

export function postSecondaryLogin(
    currentWindow: Window,
    loginResult: any
): any {
    if (BrowserUtils.isIE()) {
        /* eslint-disable no-param-reassign */
        currentWindow.localStorage.secondaryLoginResult = JSON.stringify(
            loginResult
        );
        /* eslint-enable no-param-reassign */
    } else if (currentWindow.opener) {
        currentWindow.opener.postMessage(loginResult);
    } else {
        currentWindow.close();
    }
    return loginResult;
}

export default function secondaryLogin(
    glassContext: any,
    camError?: any
): Promise<any> {
    const gatewayPath = glassContext.gateway ? glassContext.gateway : "/bi";
    let loginUrl: string = window.location.origin + gatewayPath + LOGIN_PATH;
    if (camError) {
        const state = `&state=${UrlUtils.base64Encode(
            JSON.stringify(camError)
        )}`;
        loginUrl += state;
    }
    const secondaryLoginWindow: Window = window.open(loginUrl, "");
    const currentWindow = CoreUtils.getCurrentWindow();
    currentWindow.onbeforeunload = (): void => {
        if (secondaryLoginWindow) {
            secondaryLoginWindow.close();
        }
    };
    return new Promise((resolve, reject) => {
        try {
            if (secondaryLoginWindow) {
                secondaryLoginWindow.addEventListener("load", () => {
                    secondaryLoginWindow.onbeforeunload = (): void => {
                        reject(new Error("SecondaryLogin cancelled"));
                    };
                    addMessageListener(
                        secondaryLoginWindow,
                        glassContext,
                        resolve
                    );
                });
                if (BrowserUtils.isIE()) {
                    window.localStorage.removeItem("secondaryLoginResult");
                    addStorageListener(
                        secondaryLoginWindow,
                        glassContext,
                        resolve
                    );
                }
            }
        } catch (error) {
            reject(error);
        }
    }).catch(() => {
        glassContext.appController.unlockGlass();
        return Promise.reject();
    });
}
