"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CustomProtocolHandler = void 0;
const electron_1 = require("electron");
const path = __importStar(require("path"));
const url_1 = require("url");
const ElectronUtil_1 = require("./ElectronUtil");
const eventType_1 = require("./eventType");
const showDialog_1 = require("../lib/showDialog");
const getLogger_1 = require("../logging/getLogger");
const EnvironmentUtil_1 = require("../runtime/EnvironmentUtil");
const config_1 = require("../settings/config");
const WindowManager_1 = require("../window/WindowManager");
const logger = (0, getLogger_1.getLogger)(path.basename(__filename));
const CORE_PROTOCOL_PREFIX = `${config_1.config.customProtocolName}://`;
const CORE_PROTOCOL_MAX_LENGTH = 1024;
const START_SSO_FLOW = 'start-sso';
const JOIN_CONVERSATION_FLOW = 'conversation-join';
const START_LOGIN_FLOW = 'start-login';
class CustomProtocolHandler {
    constructor() {
        this.hashLocation = '';
        this.windowManager = WindowManager_1.WindowManager;
    }
    dispatchDeepLink(url) {
        return __awaiter(this, void 0, void 0, function* () {
            logger.info('Dispatching deep link ...');
            try {
                if (typeof url === 'undefined' ||
                    !url.startsWith(CORE_PROTOCOL_PREFIX) ||
                    url.length > CORE_PROTOCOL_MAX_LENGTH) {
                    (0, showDialog_1.showErrorDialog)(`Invalid deep link "${(0, ElectronUtil_1.shortenText)(url || '', CORE_PROTOCOL_MAX_LENGTH)}."`);
                    logger.info('Invalid deep link, ignoring');
                    return;
                }
                const route = new url_1.URL(url);
                if (route.host === START_SSO_FLOW) {
                    logger.info('Deep link is a SSO link, triggering SSO login ...');
                    yield this.handleSSOLogin(route);
                }
                else if (route.host === JOIN_CONVERSATION_FLOW) {
                    logger.info('Deep link is a conversation join link, triggering join ...');
                    yield this.handleJoinConversation(route);
                }
                else if (route.host === START_LOGIN_FLOW) {
                    logger.info('Deep link is a start login link, triggering new account ...');
                    yield this.handleStartLogin(route);
                }
                else {
                    logger.info('Triggering hash location change ...');
                    this.forwardHashLocation(route);
                }
            }
            catch (error) {
                logger.error(error);
            }
        });
    }
    forwardHashLocation(route) {
        const location = route.href.substr(CORE_PROTOCOL_PREFIX.length);
        this.hashLocation = `/${location}`;
        logger.info(`New hash location: "${this.hashLocation}"`);
        this.windowManager.sendActionToPrimaryWindow(eventType_1.EVENT_TYPE.WEBAPP.CHANGE_LOCATION_HASH, this.hashLocation);
    }
    handleSSOLogin(route) {
        return __awaiter(this, void 0, void 0, function* () {
            if (typeof route.pathname === 'string') {
                logger.info('Starting SSO flow ...');
                const code = route.pathname.trim().substr(1);
                try {
                    yield this.windowManager.sendActionAndFocusWindow(eventType_1.EVENT_TYPE.ACCOUNT.SSO_LOGIN, code);
                }
                catch (error) {
                    logger.error(`Cannot start SSO flow: ${error.message}`, error);
                }
            }
        });
    }
    handleJoinConversation(route) {
        return __awaiter(this, void 0, void 0, function* () {
            if (typeof route.pathname === 'string') {
                logger.info('Joining conversation ...');
                const code = route.searchParams.get('code');
                const key = route.searchParams.get('key');
                try {
                    yield this.windowManager.sendActionAndFocusWindow(eventType_1.EVENT_TYPE.ACTION.JOIN_CONVERSATION, { code, key });
                }
                catch (error) {
                    logger.error(`Cannot join conversation: ${error.message}`, error);
                }
            }
        });
    }
    handleStartLogin(route) {
        return __awaiter(this, void 0, void 0, function* () {
            if (typeof route.pathname === 'string') {
                logger.info('Starting login flow ...');
                try {
                    yield this.windowManager.sendActionAndFocusWindow(eventType_1.EVENT_TYPE.ACTION.START_LOGIN);
                }
                catch (error) {
                    logger.error(`Cannot start login flow: ${error.message}`, error);
                }
            }
        });
    }
    findDeepLink(argv) {
        return argv.find(arg => arg.startsWith(CORE_PROTOCOL_PREFIX));
    }
    registerCoreProtocol() {
        if (electron_1.app.isDefaultProtocolClient(config_1.config.customProtocolName)) {
            logger.info(`Custom protocol "${config_1.config.customProtocolName}" already registered`);
        }
        else {
            logger.info(`Registering custom protocol "${config_1.config.customProtocolName}" ...`);
            electron_1.app.setAsDefaultProtocolClient(config_1.config.customProtocolName);
        }
        electron_1.ipcMain.on(eventType_1.EVENT_TYPE.ACTION.DEEP_LINK_SUBMIT, (_event, url) => __awaiter(this, void 0, void 0, function* () { return this.dispatchDeepLink(url); }));
        electron_1.app.on('open-url', (event, url) => __awaiter(this, void 0, void 0, function* () {
            event.preventDefault();
            yield this.dispatchDeepLink(url);
        }));
        electron_1.app.once('ready', () => __awaiter(this, void 0, void 0, function* () {
            logger.info('App ready, looking for deep link in arguments ...');
            const deepLink = this.findDeepLink(process.argv);
            if (deepLink) {
                yield this.dispatchDeepLink(deepLink);
            }
            else {
                logger.info('No deep link found in arguments.');
            }
        }));
        if (!EnvironmentUtil_1.platform.IS_MAC_OS) {
            electron_1.app.on('second-instance', (_event, argv) => __awaiter(this, void 0, void 0, function* () {
                logger.info('Second instance detected, looking for deep link in arguments ...');
                const deepLink = this.findDeepLink(argv);
                if (deepLink) {
                    yield this.dispatchDeepLink(deepLink);
                }
                else {
                    logger.info('No deep link found in arguments.');
                }
            }));
        }
    }
}
exports.CustomProtocolHandler = CustomProtocolHandler;
//# sourceMappingURL=CoreProtocol.js.map