/**
 * 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 crypto from 'crypto';
import fs from 'fs';
import os from 'os';
import path from 'path';
import { packageRoot, packageJSON } from '../../package';
export function clientKey(clientInfo) {
    return clientInfo.workspaceDir || clientInfo.workspaceDirHash;
}
export class Registry {
    _files;
    constructor(files) {
        this._files = files;
    }
    entry(clientInfo, sessionName) {
        const key = clientKey(clientInfo);
        const entries = this._files.get(key) || [];
        return entries.find(entry => entry.config.name === sessionName);
    }
    entries(clientInfo) {
        return this._files.get(clientKey(clientInfo)) || [];
    }
    entryMap() {
        return this._files;
    }
    async loadEntry(clientInfo, sessionName) {
        const entry = await Registry._loadSessionEntry(clientInfo.daemonProfilesDir, sessionName + '.session');
        if (!entry)
            throw new Error(`Could not start the session "${sessionName}"`);
        const key = clientKey(clientInfo);
        let list = this._files.get(key);
        if (!list) {
            list = [];
            this._files.set(key, list);
        }
        const oldIndex = list.findIndex(e => e.config.name === sessionName);
        if (oldIndex !== -1)
            list.splice(oldIndex, 1);
        list.push(entry);
        return entry;
    }
    static async _loadSessionEntry(daemonDir, file) {
        try {
            const fileName = path.join(daemonDir, file);
            const data = await fs.promises.readFile(fileName, 'utf-8');
            const config = JSON.parse(data);
            // Sessions from 0.1.0 support.
            if (!config.name)
                config.name = path.basename(file, '.session');
            if (!config.timestamp)
                config.timestamp = 0;
            return { file: fileName, config, daemonDir };
        }
        catch {
            return undefined;
        }
    }
    static async load() {
        const sessions = new Map();
        const hashDirs = await fs.promises.readdir(baseDaemonDir).catch(() => []);
        for (const workspaceDirHash of hashDirs) {
            const daemonDir = path.join(baseDaemonDir, workspaceDirHash);
            const stat = await fs.promises.stat(daemonDir);
            if (!stat.isDirectory())
                continue;
            const files = await fs.promises.readdir(daemonDir).catch(() => []);
            for (const file of files) {
                if (!file.endsWith('.session'))
                    continue;
                const entry = await Registry._loadSessionEntry(daemonDir, file);
                if (!entry)
                    continue;
                const key = entry.config.workspaceDir || workspaceDirHash;
                let list = sessions.get(key);
                if (!list) {
                    list = [];
                    sessions.set(key, list);
                }
                list.push(entry);
            }
        }
        return new Registry(sessions);
    }
}
export const baseDaemonDir = (() => {
    if (process.env.PLAYWRIGHT_DAEMON_SESSION_DIR)
        return process.env.PLAYWRIGHT_DAEMON_SESSION_DIR;
    let localCacheDir;
    if (process.platform === 'linux')
        localCacheDir = process.env.XDG_CACHE_HOME || path.join(os.homedir(), '.cache');
    if (process.platform === 'darwin')
        localCacheDir = path.join(os.homedir(), 'Library', 'Caches');
    if (process.platform === 'win32')
        localCacheDir = process.env.LOCALAPPDATA || path.join(os.homedir(), 'AppData', 'Local');
    if (!localCacheDir)
        throw new Error('Unsupported platform: ' + process.platform);
    return path.join(localCacheDir, 'ms-playwright', 'daemon');
})();
export function createClientInfo() {
    const workspaceDir = findWorkspaceDir(process.cwd());
    const version = process.env.PLAYWRIGHT_CLI_VERSION_FOR_TEST || packageJSON.version;
    const hash = crypto.createHash('sha1');
    hash.update(workspaceDir || packageRoot);
    const workspaceDirHash = hash.digest('hex').substring(0, 16);
    return {
        version,
        workspaceDir,
        workspaceDirHash,
        daemonProfilesDir: daemonProfilesDir(workspaceDirHash),
        homeDir: os.homedir(),
    };
}
function findWorkspaceDir(startDir) {
    let dir = startDir;
    for (let i = 0; i < 10; i++) {
        if (fs.existsSync(path.join(dir, '.playwright')))
            return dir;
        const parentDir = path.dirname(dir);
        if (parentDir === dir)
            break;
        dir = parentDir;
    }
    return undefined;
}
const daemonProfilesDir = (workspaceDirHash) => {
    return path.join(baseDaemonDir, workspaceDirHash);
};
export function explicitSessionName(sessionName) {
    return sessionName || process.env.PLAYWRIGHT_CLI_SESSION;
}
export function resolveSessionName(sessionName) {
    return explicitSessionName(sessionName) || 'default';
}
//# sourceMappingURL=registry.js.map