/**
 * Copyright (c) Microsoft Corporation. All rights reserved.
 *
 * 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 { EventEmitter } from 'events';
import { createGuid } from '@utils/crypto';
import { debugLogger } from '@utils/debugLogger';
export class SdkObject extends EventEmitter {
    guid;
    attribution;
    instrumentation;
    logName;
    constructor(parent, guidPrefix, guid) {
        super();
        this.guid = guid || `${guidPrefix || ''}@${createGuid()}`;
        this.setMaxListeners(0);
        this.attribution = { ...parent.attribution };
        this.instrumentation = parent.instrumentation;
    }
    apiLog(message) {
        if (!this.attribution.playwright.options.isInternalPlaywright)
            debugLogger.log('api', message);
    }
    closeReason() {
        return this.attribution.worker?._closeReason ||
            this.attribution.page?._closeReason ||
            this.attribution.context?._closeReason ||
            this.attribution.browser?._closeReason;
    }
}
export function createRootSdkObject() {
    const fakeParent = { attribution: {}, instrumentation: createInstrumentation() };
    const root = new SdkObject(fakeParent);
    root.guid = '';
    return root;
}
export function createInstrumentation() {
    const listeners = new Map();
    return new Proxy({}, {
        get: (obj, prop) => {
            if (typeof prop !== 'string')
                return obj[prop];
            if (prop === 'addListener')
                return (listener, context) => listeners.set(listener, context);
            if (prop === 'removeListener')
                return (listener) => listeners.delete(listener);
            if (!prop.startsWith('on'))
                return obj[prop];
            return async (sdkObject, ...params) => {
                for (const [listener, context] of listeners) {
                    if (!context || sdkObject.attribution.context === context)
                        await listener[prop]?.(sdkObject, ...params);
                }
            };
        },
    });
}
//# sourceMappingURL=instrumentation.js.map