"use strict";
/**
 * Copyright (c) Microsoft Corporation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.ElectronApplication = exports.Electron = void 0;
const browserContext_1 = require("./browserContext");
const channelOwner_1 = require("./channelOwner");
const page_1 = require("./page");
const jsHandle_1 = require("./jsHandle");
const timeoutSettings_1 = require("../utils/timeoutSettings");
const waiter_1 = require("./waiter");
const events_1 = require("./events");
const clientHelper_1 = require("./clientHelper");
class Electron extends channelOwner_1.ChannelOwner {
    static from(electron) {
        return electron._object;
    }
    constructor(parent, type, guid, initializer) {
        super(parent, type, guid, initializer);
    }
    async launch(executablePath, options = {}) {
        const logger = options.logger;
        options = { ...options, logger: undefined };
        return this._wrapApiCall('electron.launch', async () => {
            const params = {
                ...options,
                env: options.env ? clientHelper_1.envObjectToArray(options.env) : undefined,
                executablePath,
            };
            return ElectronApplication.from((await this._channel.launch(params)).electronApplication);
        }, logger);
    }
}
exports.Electron = Electron;
class ElectronApplication extends channelOwner_1.ChannelOwner {
    constructor(parent, type, guid, initializer) {
        super(parent, type, guid, initializer);
        this._windows = new Set();
        this._timeoutSettings = new timeoutSettings_1.TimeoutSettings();
        this._channel.on('context', ({ context }) => this._context = browserContext_1.BrowserContext.from(context));
        this._channel.on('window', ({ page, browserWindow }) => {
            const window = page_1.Page.from(page);
            window.browserWindow = jsHandle_1.JSHandle.from(browserWindow);
            this._windows.add(window);
            this.emit(events_1.Events.ElectronApplication.Window, window);
            window.once(events_1.Events.Page.Close, () => this._windows.delete(window));
        });
        this._channel.on('close', () => this.emit(events_1.Events.ElectronApplication.Close));
    }
    static from(electronApplication) {
        return electronApplication._object;
    }
    windows() {
        // TODO: add ElectronPage class inherting from Page.
        return [...this._windows];
    }
    async firstWindow() {
        return this._wrapApiCall('electronApplication.firstWindow', async () => {
            if (this._windows.size)
                return this._windows.values().next().value;
            return this.waitForEvent('window');
        });
    }
    async newBrowserWindow(options) {
        return this._wrapApiCall('electronApplication.newBrowserWindow', async () => {
            const result = await this._channel.newBrowserWindow({ arg: jsHandle_1.serializeArgument(options) });
            return page_1.Page.from(result.page);
        });
    }
    context() {
        return this._context;
    }
    async close() {
        await this._channel.close();
    }
    async waitForEvent(event, optionsOrPredicate = {}) {
        const timeout = this._timeoutSettings.timeout(typeof optionsOrPredicate === 'function' ? {} : optionsOrPredicate);
        const predicate = typeof optionsOrPredicate === 'function' ? optionsOrPredicate : optionsOrPredicate.predicate;
        const waiter = new waiter_1.Waiter();
        waiter.rejectOnTimeout(timeout, `Timeout while waiting for event "${event}"`);
        if (event !== events_1.Events.ElectronApplication.Close)
            waiter.rejectOnEvent(this, events_1.Events.ElectronApplication.Close, new Error('Electron application closed'));
        const result = await waiter.waitForEvent(this, event, predicate);
        waiter.dispose();
        return result;
    }
    async evaluate(pageFunction, arg) {
        return this._wrapApiCall('electronApplication.evaluate', async () => {
            const result = await this._channel.evaluateExpression({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: jsHandle_1.serializeArgument(arg) });
            return jsHandle_1.parseResult(result.value);
        });
    }
    async evaluateHandle(pageFunction, arg) {
        return this._wrapApiCall('electronApplication.evaluateHandle', async () => {
            const result = await this._channel.evaluateExpressionHandle({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: jsHandle_1.serializeArgument(arg) });
            return jsHandle_1.JSHandle.from(result.handle);
        });
    }
}
exports.ElectronApplication = ElectronApplication;
//# sourceMappingURL=electron.js.map