/**
 * 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.
 */
import { assert } from '@isomorphic/assert';
import { headersObjectToArray } from '@isomorphic/headers';
import { Browser } from './browser';
import { BrowserContext, prepareBrowserContextParams } from './browserContext';
import { ChannelOwner } from './channelOwner';
import { envObjectToArray } from './clientHelper';
import { connectToBrowser } from './connect';
import { TimeoutSettings } from './timeoutSettings';
import { Worker } from './worker';
export class BrowserType extends ChannelOwner {
    _serverLauncher;
    _contexts = new Set();
    _playwright;
    static from(browserType) {
        return browserType._object;
    }
    executablePath() {
        if (!this._initializer.executablePath)
            throw new Error('Browser is not supported on current platform');
        return this._initializer.executablePath;
    }
    name() {
        return this._initializer.name;
    }
    async launch(options = {}) {
        assert(!options.userDataDir, 'userDataDir option is not supported in `browserType.launch`. Use `browserType.launchPersistentContext` instead');
        assert(!options.port, 'Cannot specify a port without launching as a server.');
        const logger = options.logger || this._playwright._defaultLaunchOptions?.logger;
        options = { ...this._playwright._defaultLaunchOptions, ...options };
        const launchOptions = {
            ...options,
            ignoreDefaultArgs: Array.isArray(options.ignoreDefaultArgs) ? options.ignoreDefaultArgs : undefined,
            ignoreAllDefaultArgs: !!options.ignoreDefaultArgs && !Array.isArray(options.ignoreDefaultArgs),
            env: options.env ? envObjectToArray(options.env) : undefined,
            timeout: new TimeoutSettings(this._platform).launchTimeout(options),
        };
        return await this._wrapApiCall(async () => {
            const browser = Browser.from((await this._channel.launch(launchOptions)).browser);
            browser._connectToBrowserType(this, options, logger);
            return browser;
        });
    }
    async launchServer(options = {}) {
        if (!this._serverLauncher)
            throw new Error('Launching server is not supported');
        options = { ...this._playwright._defaultLaunchOptions, ...options };
        return await this._serverLauncher.launchServer(options);
    }
    async launchPersistentContext(userDataDir, options = {}) {
        assert(!options.port, 'Cannot specify a port without launching as a server.');
        options = this._playwright.selectors._withSelectorOptions({
            ...this._playwright._defaultLaunchOptions,
            ...options,
        });
        await this._instrumentation.runBeforeCreateBrowserContext(options);
        const logger = options.logger || this._playwright._defaultLaunchOptions?.logger;
        const contextParams = await prepareBrowserContextParams(this._platform, options);
        const persistentParams = {
            ...contextParams,
            ignoreDefaultArgs: Array.isArray(options.ignoreDefaultArgs) ? options.ignoreDefaultArgs : undefined,
            ignoreAllDefaultArgs: !!options.ignoreDefaultArgs && !Array.isArray(options.ignoreDefaultArgs),
            env: options.env ? envObjectToArray(options.env) : undefined,
            channel: options.channel,
            userDataDir: (this._platform.path().isAbsolute(userDataDir) || !userDataDir) ? userDataDir : this._platform.path().resolve(userDataDir),
            timeout: new TimeoutSettings(this._platform).launchTimeout(options),
        };
        const context = await this._wrapApiCall(async () => {
            const result = await this._channel.launchPersistentContext(persistentParams);
            const browser = Browser.from(result.browser);
            browser._connectToBrowserType(this, options, logger);
            const context = BrowserContext.from(result.context);
            await context._initializeHarFromOptions(options.recordHar);
            return context;
        });
        await this._instrumentation.runAfterCreateBrowserContext(context);
        return context;
    }
    async connect(optionsOrEndpoint, options) {
        if (typeof optionsOrEndpoint === 'string')
            return await this._connect({ ...options, endpoint: optionsOrEndpoint });
        assert(optionsOrEndpoint.wsEndpoint, 'options.wsEndpoint is required');
        return await this._connect({ ...options, endpoint: optionsOrEndpoint.wsEndpoint });
    }
    async _connect(params) {
        return await this._wrapApiCall(async () => {
            const browser = await connectToBrowser(this._playwright, { browserName: this.name(), ...params });
            browser._connectToBrowserType(this, {}, undefined);
            return browser;
        });
    }
    async connectOverCDP(endpointURLOrOptions, options) {
        if (typeof endpointURLOrOptions === 'string')
            return await this._connectOverCDP(endpointURLOrOptions, options);
        const endpointURL = 'endpointURL' in endpointURLOrOptions ? endpointURLOrOptions.endpointURL : endpointURLOrOptions.wsEndpoint;
        assert(endpointURL, 'Cannot connect over CDP without wsEndpoint.');
        return await this.connectOverCDP(endpointURL, endpointURLOrOptions);
    }
    async _connectOverCDP(endpointURL, params = {}) {
        if (this.name() !== 'chromium')
            throw new Error('Connecting over CDP is only supported in Chromium.');
        const headers = params.headers ? headersObjectToArray(params.headers) : undefined;
        const result = await this._channel.connectOverCDP({
            endpointURL,
            headers,
            slowMo: params.slowMo,
            timeout: new TimeoutSettings(this._platform).timeout(params),
            isLocal: params.isLocal,
            noDefaults: params.noDefaults,
        });
        const browser = Browser.from(result.browser);
        browser._connectToBrowserType(this, {}, undefined);
        if (result.defaultContext)
            await this._instrumentation.runAfterCreateBrowserContext(BrowserContext.from(result.defaultContext));
        return browser;
    }
    async _connectToWorker(endpoint, options = {}) {
        if (this.name() !== 'chromium')
            throw new Error('Connecting to workers is only supported in Chromium.');
        const result = await this._channel.connectToWorker({
            endpoint,
            timeout: new TimeoutSettings(this._platform).timeout(options),
        });
        return Worker.from(result.worker);
    }
}
//# sourceMappingURL=browserType.js.map