
import { onUnexpectedExternalError } from '../../../base/common/errors.js';
import { toDisposable } from '../../../base/common/lifecycle.js';
import { ThemeIcon } from '../../../base/common/themables.js';
import { MainContext } from './extHost.protocol.js';
import { ChatResponseProgressPart as ChatResponseProgressPart$1, ChatResponseReferencePart as ChatResponseReferencePart$1 } from './extHostTypeConverters.js';
import { ChatResponseProgressPart, ChatResponseReferencePart } from './extHostTypes.js';
import { checkProposedApiEnabled } from '../../services/extensions/common/extensions.js';

class ExtHostChatVariables {
    static { this._idPool = 0; }
    constructor(mainContext) {
        this._resolver = ( new Map());
        this._proxy = ( mainContext.getProxy(MainContext.MainThreadChatVariables));
    }
    async $resolveVariable(handle, requestId, messageText, token) {
        const item = this._resolver.get(handle);
        if (!item) {
            return undefined;
        }
        try {
            if (item.resolver.resolve2) {
                checkProposedApiEnabled(item.extension, 'chatParticipantAdditions');
                const stream = ( new ChatVariableResolverResponseStream(requestId, this._proxy));
                const value = await item.resolver.resolve2(item.data.name, { prompt: messageText }, stream.apiObject, token);
                if (value && value[0]) {
                    return value[0].value;
                }
            }
            else {
                const value = await item.resolver.resolve(item.data.name, { prompt: messageText }, token);
                if (value && value[0]) {
                    return value[0].value;
                }
            }
        }
        catch (err) {
            onUnexpectedExternalError(err);
        }
        return undefined;
    }
    registerVariableResolver(extension, id, name, userDescription, modelDescription, isSlow, resolver, fullName, themeIconId) {
        const handle = ExtHostChatVariables._idPool++;
        const icon = themeIconId ? ThemeIcon.fromId(themeIconId) : undefined;
        this._resolver.set(handle, { extension, data: { id, name, description: userDescription, modelDescription, icon }, resolver: resolver });
        this._proxy.$registerVariable(handle, { id, name, description: userDescription, modelDescription, isSlow, fullName, icon });
        return toDisposable(() => {
            this._resolver.delete(handle);
            this._proxy.$unregisterVariable(handle);
        });
    }
}
class ChatVariableResolverResponseStream {
    constructor(_requestId, _proxy) {
        this._requestId = _requestId;
        this._proxy = _proxy;
        this._isClosed = false;
    }
    close() {
        this._isClosed = true;
    }
    get apiObject() {
        if (!this._apiObject) {
            const that = this;
            function throwIfDone(source) {
                if (that._isClosed) {
                    const err = ( new Error('Response stream has been closed'));
                    Error.captureStackTrace(err, source);
                    throw err;
                }
            }
            const _report = (progress) => {
                this._proxy.$handleProgressChunk(this._requestId, progress);
            };
            this._apiObject = {
                progress(value) {
                    throwIfDone(this.progress);
                    const part = new ChatResponseProgressPart(value);
                    const dto = ChatResponseProgressPart$1.from(part);
                    _report(dto);
                    return this;
                },
                reference(value) {
                    throwIfDone(this.reference);
                    const part = new ChatResponseReferencePart(value);
                    const dto = ChatResponseReferencePart$1.from(part);
                    _report(dto);
                    return this;
                },
                push(part) {
                    throwIfDone(this.push);
                    if (part instanceof ChatResponseReferencePart) {
                        _report(ChatResponseReferencePart$1.from(part));
                    }
                    else if (part instanceof ChatResponseProgressPart) {
                        _report(ChatResponseProgressPart$1.from(part));
                    }
                    return this;
                }
            };
        }
        return this._apiObject;
    }
}

export { ExtHostChatVariables };
