/**
 * 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.
 */
/* eslint-disable no-console */
/* eslint-disable no-restricted-properties */
import path from 'path';
import { playwrightExtensionInstallUrl } from '../utils/extension';
export class TextOutput {
    json = false;
    version(v) {
        console.log(v);
    }
    help(text) {
        console.log(text);
    }
    errorUnknownCommand(name, globalHelp) {
        console.error(`Unknown command: ${name}\n`);
        console.log(globalHelp);
        return process.exit(1);
    }
    errorUnknownOption(opts, commandHelp) {
        console.error(`Unknown option${opts.length > 1 ? 's' : ''}: ${opts.map(f => `--${f}`).join(', ')}`);
        console.log('');
        console.log(commandHelp);
        return process.exit(1);
    }
    errorTooManyArguments(expected, received, commandHelp) {
        console.error(`error: too many arguments: expected ${expected}, received ${received}`);
        console.log('');
        console.log(commandHelp);
        return process.exit(1);
    }
    errorAttachConflict() {
        console.error(`Error: cannot use target name with --cdp, --endpoint, or --extension`);
        return process.exit(1);
    }
    errorDetachNotAttached(session) {
        console.error(`Error: session '${session}' was not attached; use \`playwright-cli${session !== 'default' ? ` -s=${session}` : ''} close\` to stop it.`);
        return process.exit(1);
    }
    errorBrowserNotOpenForTool(session) {
        console.log(`The browser '${session}' is not open, please run open first`);
        console.log('');
        console.log(`  playwright-cli${session !== 'default' ? ` -s=${session}` : ''} open [params]`);
        return process.exit(1);
    }
    errorAttachNoTarget() {
        console.error(`Error: no target specified for attach command; use one of [name], --cdp, --endpoint, or --extension to specify the target to attach to.`);
        return process.exit(1);
    }
    list({ all, browsers, servers, channelSessions }) {
        const byWorkspace = new Map();
        for (const browser of browsers) {
            let list = byWorkspace.get(browser.workspace);
            if (!list) {
                list = [];
                byWorkspace.set(browser.workspace, list);
            }
            list.push(browser);
        }
        let count = 0;
        for (const [workspaceKey, list] of byWorkspace) {
            if (count === 0)
                console.log('### Browsers');
            if (all)
                console.log(`${path.relative(process.cwd(), workspaceKey) || '/'}:`);
            for (const browser of list)
                console.log(renderBrowser(browser));
            count += list.length;
        }
        if (!all) {
            if (!count)
                console.log('  (no browsers)');
            return;
        }
        if (servers?.length) {
            if (count)
                console.log('');
            console.log('### Browser servers available for attach');
            const serversByWorkspace = new Map();
            for (const server of servers) {
                let list = serversByWorkspace.get(server.workspaceDir ?? '');
                if (!list) {
                    list = [];
                    serversByWorkspace.set(server.workspaceDir ?? '', list);
                }
                list.push(server);
            }
            for (const [workspaceKey, list] of serversByWorkspace) {
                if (workspaceKey)
                    console.log(`${path.relative(process.cwd(), workspaceKey) || '/'}:`);
                for (const server of list)
                    console.log(renderServer(server));
            }
            count += servers.length;
        }
        if (!count)
            console.log('  (no browsers)');
        if (channelSessions?.length) {
            console.log('');
            console.log('### Browsers available to attach via CDP');
            for (const session of channelSessions)
                console.log(renderChannelSession(session));
        }
    }
    closeAll(_sessions) {
        // Text mode is intentionally silent, matching historical behavior.
    }
    deleteData(session, result) {
        if (!result.existed) {
            console.log(`No user data found for browser '${session}'.`);
            return;
        }
        if (result.deletedUserDataDir)
            console.log(`Deleted user data for browser '${session}'.`);
    }
    killAll(pids) {
        for (const pid of pids)
            console.log(`Killed daemon process ${pid}`);
        if (pids.length === 0)
            console.log('No daemon processes found.');
        else
            console.log(`Killed ${pids.length} daemon process${pids.length === 1 ? '' : 'es'}.`);
    }
    open(session, pid, toolResult) {
        console.log(`### Browser \`${session}\` opened with pid ${pid}.`);
        if (toolResult)
            console.log(toolResult);
    }
    attach(session, pid, endpoint, toolResult) {
        if (endpoint) {
            console.log(`### Session \`${session}\` created, attached to \`${endpoint}\`.`);
            console.log(`Run commands with: playwright-cli --s=${session} <command>`);
            console.log('');
        }
        else {
            console.log(`### Browser \`${session}\` opened with pid ${pid}.`);
        }
        if (toolResult)
            console.log(toolResult);
    }
    close(session, wasOpen) {
        if (!wasOpen) {
            console.log(`Browser '${session}' is not open.`);
            return;
        }
        console.log(`Browser '${session}' closed\n`);
    }
    detach(session, wasAttached) {
        if (!wasAttached) {
            console.log(`Browser '${session}' is not attached.`);
            return;
        }
        console.log(`Browser '${session}' detached\n`);
    }
    installed() {
        // The spawned install subprocess handles its own output.
    }
    show(_session, pid) {
        if (process.env.PWTEST_PRINT_DASHBOARD_PID_FOR_TEST)
            console.log(`### Dashboard opened with pid ${pid}.`);
    }
    toolResult(text) {
        console.log(text);
    }
    installStdio() {
        return 'inherit';
    }
}
export class JsonOutput {
    json = true;
    version(v) {
        this._emit({ version: v });
    }
    help(text) {
        this._emit({ help: text });
    }
    errorUnknownCommand(name, _globalHelp) {
        this._emit({ isError: true, error: `Unknown command: ${name}` });
        return process.exit(1);
    }
    errorUnknownOption(opts, _commandHelp) {
        this._emit({ isError: true, error: `Unknown option${opts.length > 1 ? 's' : ''}: ${opts.map(f => `--${f}`).join(', ')}` });
        return process.exit(1);
    }
    errorTooManyArguments(expected, received, _commandHelp) {
        this._emit({ isError: true, error: `error: too many arguments: expected ${expected}, received ${received}` });
        return process.exit(1);
    }
    errorAttachConflict() {
        this._emit({ isError: true, error: `cannot use target name with --cdp, --endpoint, or --extension` });
        return process.exit(1);
    }
    errorDetachNotAttached(session) {
        this._emit({ isError: true, error: `session '${session}' was not attached; use close to stop it.` });
        return process.exit(1);
    }
    errorBrowserNotOpenForTool(session) {
        this._emit({ isError: true, error: `The browser '${session}' is not open, please run open first` });
        return process.exit(1);
    }
    errorAttachNoTarget() {
        this._emit({ isError: true, error: `no target specified for attach command; use one of [name], --cdp, --endpoint, or --extension to specify the target to attach to.` });
        return process.exit(1);
    }
    list({ all, browsers, servers, channelSessions }) {
        const payload = { browsers };
        if (all) {
            payload.servers = servers ?? [];
            payload.channelSessions = channelSessions ?? [];
        }
        this._emit(payload);
    }
    closeAll(sessions) {
        this._emit({ closed: sessions });
    }
    deleteData(session, result) {
        this._emit({ session, deleted: result.existed });
    }
    killAll(pids) {
        this._emit({ killed: pids.length, pids });
    }
    open(session, pid, toolResult) {
        this._emit({ session, pid, result: parseJsonText(toolResult) });
    }
    attach(session, pid, endpoint, toolResult) {
        this._emit({
            session,
            pid,
            ...(endpoint ? { endpoint } : {}),
            result: parseJsonText(toolResult),
        });
    }
    close(session, wasOpen) {
        this._emit({ session, status: wasOpen ? 'closed' : 'not-open' });
    }
    detach(session, wasAttached) {
        this._emit({ session, status: wasAttached ? 'detached' : 'not-attached' });
    }
    installed() {
        this._emit({ installed: true });
    }
    show(session, pid) {
        this._emit({ session, pid });
    }
    toolResult(text) {
        // Daemon already returns pretty-printed JSON, write through verbatim.
        console.log(text);
    }
    installStdio() {
        return 'ignore';
    }
    _emit(value) {
        console.log(JSON.stringify(value, null, 2));
    }
}
function parseJsonText(text) {
    try {
        return JSON.parse(text);
    }
    catch {
        return text;
    }
}
function renderBrowser(browser) {
    const lines = [`- ${browser.name}:`];
    lines.push(`  - status: ${browser.status}`);
    if (browser.status === 'open' && !browser.compatible)
        lines.push(`  - version: v${browser.version} [incompatible please re-open]`);
    if (browser.browserType)
        lines.push(`  - browser-type: ${browser.browserType}${browser.attached ? ' (attached)' : ''}`);
    if (!browser.attached) {
        if (browser.userDataDir === null)
            lines.push(`  - user-data-dir: <in-memory>`);
        else
            lines.push(`  - user-data-dir: ${browser.userDataDir}`);
        if (browser.headed !== undefined)
            lines.push(`  - headed: ${browser.headed}`);
    }
    return lines.join('\n');
}
function renderServer(server) {
    const lines = [`- browser "${server.title}":`];
    lines.push(`  - browser: ${server.browser.browserName}`);
    lines.push(`  - version: v${server.playwrightVersion}`);
    if (server.browser.userDataDir)
        lines.push(`  - data-dir: ${server.browser.userDataDir}`);
    else
        lines.push(`  - data-dir: <in-memory>`);
    lines.push(`  - run \`playwright-cli attach "${server.title}"\` to attach`);
    return lines.join('\n');
}
function renderChannelSession(session) {
    const lines = [`- ${session.channel}:`];
    lines.push(`  - data-dir: ${session.userDataDir}`);
    if (session.extensionInstalled)
        lines.push(`  - attach (extension): \`playwright-cli attach --extension=${session.channel}\``);
    else
        lines.push(`  - attach (extension): install at ${playwrightExtensionInstallUrl}`);
    if (session.endpoint) {
        lines.push(`  - attach (remote debugging): \`playwright-cli attach --cdp=${session.channel}\``);
    }
    else {
        const inspectScheme = session.channel.startsWith('msedge') ? 'edge' : 'chrome';
        lines.push(`  - attach (remote debugging): enable at ${inspectScheme}://inspect/#remote-debugging`);
    }
    return lines.join('\n');
}
//# sourceMappingURL=output.js.map