"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.create = create;
const language_core_1 = require("@vue/language-core");
const volar_service_html_1 = require("volar-service-html");
const html = __importStar(require("vscode-html-languageservice"));
const data_1 = require("../data");
const utils_1 = require("../utils");
let sfcDataProvider;
function create() {
    const htmlService = (0, volar_service_html_1.create)({
        documentSelector: ['vue-root-tags'],
        useDefaultDataProvider: false,
        getCustomData(context) {
            sfcDataProvider ??= html.newHTMLDataProvider('vue', (0, data_1.loadLanguageBlocks)(context.env.locale ?? 'en'));
            return [sfcDataProvider];
        },
        async getFormattingOptions(document, options, context) {
            const info = (0, utils_1.resolveEmbeddedCode)(context, document.uri);
            if (info?.code.id !== 'root_tags') {
                return {};
            }
            const formatSettings = await context.env.getConfiguration?.('html.format') ?? {};
            const blockTypes = ['template', 'script', 'style'];
            for (const customBlock of info.root.sfc.customBlocks) {
                blockTypes.push(customBlock.type);
            }
            return {
                ...options,
                ...formatSettings,
                wrapAttributes: await context.env.getConfiguration?.('vue.format.wrapAttributes') ?? 'auto',
                unformatted: '',
                contentUnformatted: blockTypes.join(','),
                endWithNewline: options.insertFinalNewline
                    ? true
                    : options.trimFinalNewlines
                        ? false
                        : document.getText().endsWith('\n'),
            };
        },
    });
    return {
        ...htmlService,
        name: 'vue-sfc',
        capabilities: {
            ...htmlService.capabilities,
            diagnosticProvider: {
                interFileDependencies: false,
                workspaceDiagnostics: false,
            },
        },
        create(context) {
            const htmlServiceInstance = htmlService.create(context);
            return {
                ...htmlServiceInstance,
                provideDocumentLinks: undefined,
                async resolveEmbeddedCodeFormattingOptions(sourceScript, virtualCode, options) {
                    if (sourceScript.generated?.root instanceof language_core_1.VueVirtualCode) {
                        if (virtualCode.id === 'script_raw' || virtualCode.id === 'scriptsetup_raw') {
                            if (await context.env.getConfiguration?.('vue.format.script.initialIndent') ?? false) {
                                options.initialIndentLevel++;
                            }
                        }
                        else if (virtualCode.id.startsWith('style_')) {
                            if (await context.env.getConfiguration?.('vue.format.style.initialIndent') ?? false) {
                                options.initialIndentLevel++;
                            }
                        }
                        else if (virtualCode.id === 'template') {
                            if (await context.env.getConfiguration?.('vue.format.template.initialIndent') ?? true) {
                                options.initialIndentLevel++;
                            }
                        }
                    }
                    return options;
                },
                async provideDiagnostics(document, token) {
                    const info = (0, utils_1.resolveEmbeddedCode)(context, document.uri);
                    if (info?.code.id !== 'root_tags') {
                        return [];
                    }
                    const { vueSfc, sfc } = info.root;
                    if (!vueSfc) {
                        return;
                    }
                    const originalResult = await htmlServiceInstance.provideDiagnostics?.(document, token);
                    const sfcErrors = [];
                    const { template } = sfc;
                    const { startTagEnd = Infinity, endTagStart = -Infinity, } = template ?? {};
                    for (const error of vueSfc.errors) {
                        if ('code' in error) {
                            const start = error.loc?.start.offset ?? 0;
                            const end = error.loc?.end.offset ?? 0;
                            if (end < startTagEnd || start >= endTagStart) {
                                sfcErrors.push({
                                    range: {
                                        start: document.positionAt(start),
                                        end: document.positionAt(end),
                                    },
                                    severity: 1,
                                    code: error.code,
                                    source: 'vue',
                                    message: error.message,
                                });
                            }
                        }
                    }
                    return [
                        ...originalResult ?? [],
                        ...sfcErrors,
                    ];
                },
                provideDocumentSymbols(document) {
                    const info = (0, utils_1.resolveEmbeddedCode)(context, document.uri);
                    if (info?.code.id !== 'root_tags') {
                        return;
                    }
                    const result = [];
                    const { sfc } = info.root;
                    if (sfc.template) {
                        result.push({
                            name: 'template',
                            kind: 2,
                            range: {
                                start: document.positionAt(sfc.template.start),
                                end: document.positionAt(sfc.template.end),
                            },
                            selectionRange: {
                                start: document.positionAt(sfc.template.start),
                                end: document.positionAt(sfc.template.startTagEnd),
                            },
                        });
                    }
                    if (sfc.script) {
                        result.push({
                            name: 'script',
                            kind: 2,
                            range: {
                                start: document.positionAt(sfc.script.start),
                                end: document.positionAt(sfc.script.end),
                            },
                            selectionRange: {
                                start: document.positionAt(sfc.script.start),
                                end: document.positionAt(sfc.script.startTagEnd),
                            },
                        });
                    }
                    if (sfc.scriptSetup) {
                        result.push({
                            name: 'script setup',
                            kind: 2,
                            range: {
                                start: document.positionAt(sfc.scriptSetup.start),
                                end: document.positionAt(sfc.scriptSetup.end),
                            },
                            selectionRange: {
                                start: document.positionAt(sfc.scriptSetup.start),
                                end: document.positionAt(sfc.scriptSetup.startTagEnd),
                            },
                        });
                    }
                    for (const style of sfc.styles) {
                        let name = 'style';
                        if (style.scoped) {
                            name += ' scoped';
                        }
                        if (style.module) {
                            name += ' module';
                        }
                        result.push({
                            name,
                            kind: 2,
                            range: {
                                start: document.positionAt(style.start),
                                end: document.positionAt(style.end),
                            },
                            selectionRange: {
                                start: document.positionAt(style.start),
                                end: document.positionAt(style.startTagEnd),
                            },
                        });
                    }
                    for (const customBlock of sfc.customBlocks) {
                        result.push({
                            name: customBlock.type,
                            kind: 2,
                            range: {
                                start: document.positionAt(customBlock.start),
                                end: document.positionAt(customBlock.end),
                            },
                            selectionRange: {
                                start: document.positionAt(customBlock.start),
                                end: document.positionAt(customBlock.startTagEnd),
                            },
                        });
                    }
                    return result;
                },
                async provideCompletionItems(document, position, context, token) {
                    const result = await htmlServiceInstance.provideCompletionItems?.(document, position, context, token);
                    if (!result) {
                        return;
                    }
                    result.items = result.items.filter(item => item.label !== '!DOCTYPE'
                        && item.label !== 'Custom Blocks'
                        && item.label !== 'data-');
                    const tags = sfcDataProvider?.provideTags();
                    const scriptLangs = getLangs('script');
                    const scriptItems = result.items.filter(item => item.label === 'script' || item.label === 'script setup');
                    for (const scriptItem of scriptItems) {
                        scriptItem.kind = 17;
                        scriptItem.detail = '.js';
                        for (const lang of scriptLangs) {
                            result.items.push({
                                ...scriptItem,
                                detail: `.${lang}`,
                                kind: 17,
                                label: scriptItem.label + ' lang="' + lang + '"',
                                textEdit: scriptItem.textEdit
                                    ? {
                                        ...scriptItem.textEdit,
                                        newText: scriptItem.textEdit.newText + ' lang="' + lang + '"',
                                    }
                                    : undefined,
                            });
                        }
                    }
                    const styleLangs = getLangs('style');
                    const styleItem = result.items.find(item => item.label === 'style');
                    if (styleItem) {
                        styleItem.kind = 17;
                        styleItem.detail = '.css';
                        for (const lang of styleLangs) {
                            result.items.push(getStyleCompletionItem(styleItem, lang), getStyleCompletionItem(styleItem, lang, 'scoped'), getStyleCompletionItem(styleItem, lang, 'module'));
                        }
                    }
                    const templateLangs = getLangs('template');
                    const templateItem = result.items.find(item => item.label === 'template');
                    if (templateItem) {
                        templateItem.kind = 17;
                        templateItem.detail = '.html';
                        for (const lang of templateLangs) {
                            if (lang === 'html') {
                                continue;
                            }
                            result.items.push({
                                ...templateItem,
                                kind: 17,
                                detail: `.${lang}`,
                                label: templateItem.label + ' lang="' + lang + '"',
                                textEdit: templateItem.textEdit
                                    ? {
                                        ...templateItem.textEdit,
                                        newText: templateItem.textEdit.newText + ' lang="' + lang + '"',
                                    }
                                    : undefined,
                            });
                        }
                    }
                    return result;
                    function getLangs(label) {
                        return tags
                            ?.find(tag => tag.name === label)?.attributes
                            .find(attr => attr.name === 'lang')?.values
                            ?.map(({ name }) => name) ?? [];
                    }
                },
            };
        },
    };
}
function getStyleCompletionItem(styleItem, lang, attr) {
    return {
        ...styleItem,
        kind: 17,
        detail: lang === 'postcss' ? '.css' : `.${lang}`,
        label: styleItem.label + ' lang="' + lang + '"' + (attr ? ` ${attr}` : ''),
        textEdit: styleItem.textEdit
            ? {
                ...styleItem.textEdit,
                newText: styleItem.textEdit.newText + ' lang="' + lang + '"' + (attr ? ` ${attr}` : ''),
            }
            : undefined,
    };
}
//# sourceMappingURL=vue-sfc.js.map