"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Document = void 0;
const utils_1 = require("../../utils");
const DocumentBase_1 = require("./DocumentBase");
const utils_2 = require("./utils");
const parseHtml_1 = require("./parseHtml");
const configLoader_1 = require("./configLoader");
const importPackage_1 = require("../../importPackage");
/**
 * Represents a text document contains a svelte component.
 */
class Document extends DocumentBase_1.WritableDocument {
    get compiler() {
        return this.getCompiler();
    }
    get isSvelte5() {
        return this.getSvelteVersion()[0] > 4;
    }
    constructor(url, content, skipConfigLoading = false) {
        super();
        this.url = url;
        this.content = content;
        this.languageId = 'svelte';
        this.scriptInfo = null;
        this.moduleScriptInfo = null;
        this.styleInfo = null;
        this.templateInfo = null;
        this.openedByClient = false;
        /**
         * Compute and cache directly because of performance reasons
         * and it will be called anyway.
         */
        this.path = (0, utils_1.urlToPath)(this.url);
        this.configPromise = skipConfigLoading
            ? Promise.resolve(undefined)
            : configLoader_1.configLoader.awaitConfig(this.getFilePath() || '');
        this.updateDocInfo();
    }
    static createForTest(url, content) {
        return new Document(url, content, /*skipConfigLoading*/ true);
    }
    getCompiler() {
        if (!this._compiler) {
            this._compiler = (0, importPackage_1.importSvelte)(this.getFilePath() || '');
        }
        return this._compiler;
    }
    updateDocInfo() {
        this.html = (0, parseHtml_1.parseHtml)(this.content);
        const update = (config) => {
            const scriptTags = (0, utils_2.extractScriptTags)(this.content, this.html);
            this.config = config;
            this.scriptInfo = this.addDefaultLanguage(config, scriptTags?.script || null, 'script');
            this.moduleScriptInfo = this.addDefaultLanguage(config, scriptTags?.moduleScript || null, 'script');
            this.styleInfo = this.addDefaultLanguage(config, (0, utils_2.extractStyleTag)(this.content, this.html), 'style');
            this.templateInfo = this.addDefaultLanguage(config, (0, utils_2.extractTemplateTag)(this.content, this.html), 'markup');
        };
        const config = configLoader_1.configLoader.getConfig(this.getFilePath() || '');
        if (config && !config.loadConfigError) {
            update(config);
        }
        else {
            update(undefined);
            this.configPromise.then((c) => update(c));
        }
    }
    getSvelteVersion() {
        if (!this.svelteVersion) {
            const [major, minor] = this.compiler.VERSION.split('.');
            this.svelteVersion = [Number(major), Number(minor)];
        }
        return this.svelteVersion;
    }
    /**
     * Get text content
     */
    getText(range) {
        if (range) {
            return this.content.substring(this.offsetAt(range.start), this.offsetAt(range.end));
        }
        return this.content;
    }
    /**
     * Set text content and increase the document version
     */
    setText(text) {
        this.content = text;
        this.version++;
        this.lineOffsets = undefined;
        this.updateDocInfo();
    }
    /**
     * Returns the file path if the url scheme is file
     */
    getFilePath() {
        return this.path;
    }
    /**
     * Get URL file path.
     */
    getURL() {
        return this.url;
    }
    /**
     * Returns the language associated to script, style or template.
     * Returns an empty string if there's nothing set.
     */
    getLanguageAttribute(tag) {
        const attrs = (tag === 'style'
            ? this.styleInfo?.attributes
            : tag === 'script'
                ? this.scriptInfo?.attributes || this.moduleScriptInfo?.attributes
                : this.templateInfo?.attributes) || {};
        const lang = attrs.lang || attrs.type || '';
        return lang.replace(/^text\//, '');
    }
    /**
     * Returns true if there's `lang="X"` on script or style or template.
     */
    hasLanguageAttribute() {
        return (!!this.getLanguageAttribute('script') ||
            !!this.getLanguageAttribute('style') ||
            !!this.getLanguageAttribute('template'));
    }
    /**
     * @deprecated This no longer exists in svelte-preprocess v5, we leave it in in case someone is using this with v4
     */
    addDefaultLanguage(config, tagInfo, tag) {
        if (!tagInfo || !config) {
            return tagInfo;
        }
        const defaultLang = Array.isArray(config.preprocess)
            ? config.preprocess.find((group) => group.defaultLanguages?.[tag])?.defaultLanguages?.[tag]
            : config.preprocess?.defaultLanguages?.[tag];
        if (!tagInfo.attributes.lang && !tagInfo.attributes.type && defaultLang) {
            tagInfo.attributes.lang = defaultLang;
        }
        return tagInfo;
    }
}
exports.Document = Document;
//# sourceMappingURL=Document.js.map