"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const ts = require("typescript/lib/tsserverlibrary");
const vscode_css_languageservice_1 = require("vscode-css-languageservice");
const vscode = require("vscode-languageserver-types");
const config = require("./config");
const wrapperPre = ':root{\n';
class VscodeLanguageServiceAdapter {
    getCompletionsAtPosition(contents, position, context) {
        const doc = this.createTextDocumentForTemplateString(contents, context);
        const stylesheet = this.languageService.parseStylesheet(doc);
        const items = this.languageService.doComplete(doc, this.positionInDoc(position), stylesheet);
        return translateCompletionItems(items);
    }
    getQuickInfoAtPosition(contents, position, context) {
        const doc = this.createTextDocumentForTemplateString(contents, context);
        const stylesheet = this.languageService.parseStylesheet(doc);
        const hover = this.languageService.doHover(doc, this.positionInDoc(position), stylesheet);
        if (hover) {
            return this.translateHover(hover, this.positionInDoc(position), context);
        }
        return undefined;
    }
    getSemanticDiagnostics(contents, context) {
        const doc = this.createTextDocumentForTemplateString(contents, context);
        const stylesheet = this.languageService.parseStylesheet(doc);
        return this.languageService.doValidation(doc, stylesheet).map(diag => {
            const start = doc.offsetAt(diag.range.start) - wrapperPre.length;
            return translateDiagnostic(diag, context.node.getSourceFile(), start, doc.offsetAt(diag.range.end) - wrapperPre.length - start);
        });
    }
    get languageService() {
        if (!this._languageService) {
            this._languageService = vscode_css_languageservice_1.getCSSLanguageService();
        }
        return this._languageService;
    }
    createTextDocumentForTemplateString(contents, context) {
        contents = `${wrapperPre}${contents}}`;
        return {
            uri: 'untitled://embedded.css',
            languageId: 'css',
            version: 1,
            getText: () => contents,
            positionAt: (offset) => {
                const pos = context.toPosition(offset - wrapperPre.length);
                return {
                    line: pos.line + 1,
                    character: pos.character,
                };
            },
            offsetAt: (p) => {
                return context.toOffset({
                    line: p.line - 1,
                    character: p.character,
                }) + wrapperPre.length;
            },
            lineCount: contents.split(/n/g).length + 1,
        };
    }
    positionInDoc(position) {
        return {
            line: position.line + 1,
            character: position.character,
        };
    }
    positionWithinContents(position) {
        return {
            line: position.line - 1,
            character: position.character,
        };
    }
    translateHover(hover, position, context) {
        const contents = [];
        const convertPart = (hoverContents) => {
            if (typeof hoverContents === 'string') {
                contents.push({ kind: 'unknown', text: hoverContents });
            }
            else if (Array.isArray(hoverContents)) {
                hoverContents.forEach(convertPart);
            }
            else {
                contents.push({ kind: 'unknown', text: hoverContents.value });
            }
        };
        convertPart(hover.contents);
        const start = context.toOffset(this.positionWithinContents(hover.range ? hover.range.start : position));
        return {
            kind: ts.ScriptElementKind.unknown,
            kindModifiers: '',
            textSpan: {
                start,
                length: hover.range ? context.toOffset(this.positionWithinContents(hover.range.end)) - start : 1,
            },
            displayParts: [],
            documentation: contents,
            tags: [],
        };
    }
}
exports.default = VscodeLanguageServiceAdapter;
function translateCompletionItems(items) {
    return {
        isGlobalCompletion: false,
        isMemberCompletion: false,
        isNewIdentifierLocation: false,
        entries: items.items.map(translateCompetionEntry),
    };
}
function translateCompetionEntry(item) {
    return {
        name: item.label,
        kindModifiers: 'declare',
        kind: item.kind ? translateionCompletionItemKind(item.kind) : ts.ScriptElementKind.unknown,
        sortText: '0',
    };
}
function translateionCompletionItemKind(kind) {
    switch (kind) {
        case vscode.CompletionItemKind.Method:
            return ts.ScriptElementKind.memberFunctionElement;
        case vscode.CompletionItemKind.Function:
            return ts.ScriptElementKind.functionElement;
        case vscode.CompletionItemKind.Constructor:
            return ts.ScriptElementKind.constructorImplementationElement;
        case vscode.CompletionItemKind.Field:
        case vscode.CompletionItemKind.Variable:
            return ts.ScriptElementKind.variableElement;
        case vscode.CompletionItemKind.Class:
            return ts.ScriptElementKind.classElement;
        case vscode.CompletionItemKind.Interface:
            return ts.ScriptElementKind.interfaceElement;
        case vscode.CompletionItemKind.Module:
            return ts.ScriptElementKind.moduleElement;
        case vscode.CompletionItemKind.Property:
            return ts.ScriptElementKind.memberVariableElement;
        case vscode.CompletionItemKind.Unit:
        case vscode.CompletionItemKind.Value:
            return ts.ScriptElementKind.constElement;
        case vscode.CompletionItemKind.Enum:
            return ts.ScriptElementKind.enumElement;
        case vscode.CompletionItemKind.Keyword:
            return ts.ScriptElementKind.keyword;
        case vscode.CompletionItemKind.Color:
            return ts.ScriptElementKind.constElement;
        case vscode.CompletionItemKind.Reference:
            return ts.ScriptElementKind.alias;
        case vscode.CompletionItemKind.File:
            return ts.ScriptElementKind.moduleElement;
        case vscode.CompletionItemKind.Snippet:
        case vscode.CompletionItemKind.Text:
        default:
            return ts.ScriptElementKind.unknown;
    }
}
function translateDiagnostic(d, file, start, length) {
    const code = typeof d.code === 'number' ? d.code : 9999;
    const messageText = d.message.split('\n')[0];
    return {
        code,
        messageText,
        category: d.severity,
        file,
        start,
        length,
        source: config.pluginName,
    };
}
//# sourceMappingURL=vscode-language-service-adapter.js.map