"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 (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const css = __importStar(require("vscode-css-languageservice"));
const vscode = __importStar(require("vscode-languageserver-protocol"));
const path = __importStar(require("path"));
exports.default = () => (context) => {
    const triggerCharacters = {
        // https://github.com/microsoft/vscode/blob/09850876e652688fb142e2e19fd00fd38c0bc4ba/extensions/css-language-features/server/src/cssServer.ts#L97
        triggerCharacters: ['/', '-', ':'],
    };
    if (!context) {
        return triggerCharacters;
    }
    let inited = false;
    const stylesheets = new WeakMap();
    const cssLs = css.getCSSLanguageService({ fileSystemProvider: context.fileSystemProvider });
    const scssLs = css.getSCSSLanguageService({ fileSystemProvider: context.fileSystemProvider });
    const lessLs = css.getLESSLanguageService({ fileSystemProvider: context.fileSystemProvider });
    const postcssLs = {
        ...scssLs,
        doValidation: (document, stylesheet, documentSettings) => {
            let errors = scssLs.doValidation(document, stylesheet, documentSettings);
            errors = errors.filter(error => error.code !== 'css-semicolonexpected');
            errors = errors.filter(error => error.code !== 'css-ruleorselectorexpected');
            errors = errors.filter(error => error.code !== 'unknownAtRules');
            return errors;
        },
    };
    return {
        ...triggerCharacters,
        async resolveRuleContext(context) {
            await worker(context.document, (stylesheet, cssLs) => {
                context.css = {
                    stylesheet,
                    languageService: cssLs,
                };
            });
            return context;
        },
        async provideCompletionItems(document, position) {
            return worker(document, async (stylesheet, cssLs) => {
                const settings = await context.configurationHost?.getConfiguration(document.languageId);
                const cssResult = context.documentContext
                    ? await cssLs.doComplete2(document, position, stylesheet, context.documentContext, settings?.completion)
                    : await cssLs.doComplete(document, position, stylesheet, settings?.completion);
                return cssResult;
            });
        },
        provideRenameRange(document, position) {
            return worker(document, (stylesheet, cssLs) => {
                return cssLs.prepareRename(document, position, stylesheet);
            });
        },
        provideRenameEdits(document, position, newName) {
            return worker(document, (stylesheet, cssLs) => {
                return cssLs.doRename(document, position, newName, stylesheet);
            });
        },
        provideCodeActions(document, range, context) {
            return worker(document, (stylesheet, cssLs) => {
                return cssLs.doCodeActions2(document, range, context, stylesheet);
            });
        },
        provideDefinition(document, position) {
            return worker(document, (stylesheet, cssLs) => {
                const location = cssLs.findDefinition(document, position, stylesheet);
                if (location) {
                    return [vscode.LocationLink.create(location.uri, location.range, location.range)];
                }
            });
        },
        async provideSyntacticDiagnostics(document) {
            return worker(document, async (stylesheet, cssLs) => {
                const settings = await context.configurationHost?.getConfiguration(document.languageId);
                return cssLs.doValidation(document, stylesheet, settings);
            });
        },
        async provideHover(document, position) {
            return worker(document, async (stylesheet, cssLs) => {
                const settings = await context.configurationHost?.getConfiguration(document.languageId);
                return cssLs.doHover(document, position, stylesheet, settings?.hover);
            });
        },
        provideReferences(document, position) {
            return worker(document, (stylesheet, cssLs) => {
                return cssLs.findReferences(document, position, stylesheet);
            });
        },
        provideDocumentHighlights(document, position) {
            return worker(document, (stylesheet, cssLs) => {
                return cssLs.findDocumentHighlights(document, position, stylesheet);
            });
        },
        async provideDocumentLinks(document) {
            return await worker(document, (stylesheet, cssLs) => {
                if (!context.documentContext)
                    return;
                return cssLs.findDocumentLinks2(document, stylesheet, context.documentContext);
            });
        },
        provideDocumentSymbols(document) {
            return worker(document, (stylesheet, cssLs) => {
                return cssLs.findDocumentSymbols2(document, stylesheet);
            });
        },
        provideDocumentColors(document) {
            return worker(document, (stylesheet, cssLs) => {
                return cssLs.findDocumentColors(document, stylesheet);
            });
        },
        provideColorPresentations(document, color, range) {
            return worker(document, (stylesheet, cssLs) => {
                return cssLs.getColorPresentations(document, stylesheet, color, range);
            });
        },
        provideFoldingRanges(document) {
            return worker(document, (stylesheet, cssLs) => {
                return cssLs.getFoldingRanges(document, stylesheet);
            });
        },
        provideSelectionRanges(document, positions) {
            return worker(document, (stylesheet, cssLs) => {
                return cssLs.getSelectionRanges(document, positions, stylesheet);
            });
        },
        async provideDocumentFormattingEdits(document, formatRange, options) {
            return worker(document, async (_stylesheet, cssLs) => {
                const options_2 = await context.configurationHost?.getConfiguration(document.languageId + '.format');
                if (options_2?.enable === false) {
                    return;
                }
                return cssLs.format(document, formatRange, {
                    ...options_2,
                    ...options,
                });
            });
        },
    };
    async function initCustomData() {
        if (!inited) {
            context?.configurationHost?.onDidChangeConfiguration(async () => {
                const customData = await getCustomData();
                cssLs.setDataProviders(true, customData);
                scssLs.setDataProviders(true, customData);
                lessLs.setDataProviders(true, customData);
            });
            const customData = await getCustomData();
            cssLs.setDataProviders(true, customData);
            scssLs.setDataProviders(true, customData);
            lessLs.setDataProviders(true, customData);
            inited = true;
        }
    }
    async function getCustomData() {
        const configHost = context?.configurationHost;
        if (configHost) {
            const customData = await configHost.getConfiguration('css.customData') ?? [];
            const newData = [];
            for (const customDataPath of customData) {
                try {
                    const jsonPath = path.resolve(customDataPath);
                    newData.push(css.newCSSDataProvider(require(jsonPath)));
                }
                catch (error) {
                    console.error(error);
                }
            }
            return newData;
        }
        return [];
    }
    function getCssLs(lang) {
        switch (lang) {
            case 'css': return cssLs;
            case 'scss': return scssLs;
            case 'less': return lessLs;
            case 'postcss': return postcssLs;
        }
    }
    function getStylesheet(document) {
        const cache = stylesheets.get(document);
        if (cache) {
            const [cacheVersion, cacheStylesheet] = cache;
            if (cacheVersion === document.version) {
                return cacheStylesheet;
            }
        }
        const cssLs = getCssLs(document.languageId);
        if (!cssLs)
            return;
        const stylesheet = cssLs.parseStylesheet(document);
        stylesheets.set(document, [document.version, stylesheet]);
        return stylesheet;
    }
    async function worker(document, callback) {
        const stylesheet = getStylesheet(document);
        if (!stylesheet)
            return;
        const cssLs = getCssLs(document.languageId);
        if (!cssLs)
            return;
        await initCustomData();
        return callback(stylesheet, cssLs);
    }
};
//# sourceMappingURL=index.js.map