/**
 * 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 EventEmitter from 'events';
import * as socks from '@utils/socksProxy';
import { isUnderTest } from '@utils/debug';
import { ValidationError, findValidator } from '../protocol/validator';
export class SocksInterceptor {
    _handler;
    _channel;
    _socksSupportObjectGuid;
    _ids = new Set();
    constructor(transport, pattern, redirectPortForTest) {
        this._handler = new socks.SocksProxyHandler(pattern, redirectPortForTest);
        let lastId = -1;
        this._channel = new Proxy(new EventEmitter(), {
            get: (obj, prop) => {
                if ((prop in obj) || obj[prop] !== undefined || typeof prop !== 'string')
                    return obj[prop];
                return (params) => {
                    try {
                        const id = --lastId;
                        this._ids.add(id);
                        const validator = findValidator('SocksSupport', prop, 'Params');
                        params = validator(params, '', { tChannelImpl: tChannelForSocks, binary: 'toBase64', isUnderTest });
                        transport.send({ id, guid: this._socksSupportObjectGuid, method: prop, params, metadata: { stack: [], apiName: '', internal: true } });
                    }
                    catch (e) {
                    }
                };
            },
        });
        this._handler.on(socks.SocksProxyHandler.Events.SocksConnected, (payload) => this._channel.socksConnected(payload));
        this._handler.on(socks.SocksProxyHandler.Events.SocksData, (payload) => this._channel.socksData(payload));
        this._handler.on(socks.SocksProxyHandler.Events.SocksError, (payload) => this._channel.socksError(payload));
        this._handler.on(socks.SocksProxyHandler.Events.SocksFailed, (payload) => this._channel.socksFailed(payload));
        this._handler.on(socks.SocksProxyHandler.Events.SocksEnd, (payload) => this._channel.socksEnd(payload));
        this._channel.on('socksRequested', payload => this._handler.socketRequested(payload));
        this._channel.on('socksClosed', payload => this._handler.socketClosed(payload));
        this._channel.on('socksData', payload => this._handler.sendSocketData(payload));
    }
    cleanup() {
        this._handler.cleanup();
    }
    interceptMessage(message) {
        if (this._ids.has(message.id)) {
            this._ids.delete(message.id);
            return true;
        }
        if (message.method === '__create__' && message.params.type === 'SocksSupport') {
            this._socksSupportObjectGuid = message.params.guid;
            return false;
        }
        if (this._socksSupportObjectGuid && message.guid === this._socksSupportObjectGuid) {
            const validator = findValidator('SocksSupport', message.method, 'Event');
            const params = validator(message.params, '', { tChannelImpl: tChannelForSocks, binary: 'fromBase64', isUnderTest });
            this._channel.emit(message.method, params);
            return true;
        }
        return false;
    }
}
function tChannelForSocks(names, arg, path, context) {
    throw new ValidationError(`${path}: channels are not expected in SocksSupport`);
}
//# sourceMappingURL=socksInterceptor.js.map