"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getPathCompletionParticipant = void 0;
const path = require("path");
const fs = require("fs");
const vscode_uri_1 = require("vscode-uri");
const languageModes_1 = require("./languageModes");
const strings_1 = require("../utils/strings");
const arrays_1 = require("../utils/arrays");
function getPathCompletionParticipant(document, workspaceFolders, result) {
    return {
        onHtmlAttributeValue: ({ tag, attribute, value: valueBeforeCursor, range }) => {
            const fullValue = stripQuotes(document.getText(range));
            if (shouldDoPathCompletion(tag, attribute, fullValue)) {
                if (workspaceFolders.length === 0) {
                    return;
                }
                const workspaceRoot = resolveWorkspaceRoot(document, workspaceFolders);
                const paths = providePaths(valueBeforeCursor, vscode_uri_1.URI.parse(document.uri).fsPath, workspaceRoot);
                result.push(...paths.map(p => pathToSuggestion(p, valueBeforeCursor, fullValue, range)));
            }
        }
    };
}
exports.getPathCompletionParticipant = getPathCompletionParticipant;
function stripQuotes(fullValue) {
    if (strings_1.startsWith(fullValue, `'`) || strings_1.startsWith(fullValue, `"`)) {
        return fullValue.slice(1, -1);
    }
    else {
        return fullValue;
    }
}
function shouldDoPathCompletion(tag, attr, value) {
    if (strings_1.startsWith(value, 'http') || strings_1.startsWith(value, 'https') || strings_1.startsWith(value, '//')) {
        return false;
    }
    if (PATH_TAG_AND_ATTR[tag]) {
        if (typeof PATH_TAG_AND_ATTR[tag] === 'string') {
            return PATH_TAG_AND_ATTR[tag] === attr;
        }
        else {
            return arrays_1.contains(PATH_TAG_AND_ATTR[tag], attr);
        }
    }
    return false;
}
function providePaths(valueBeforeCursor, activeDocFsPath, root) {
    const lastIndexOfSlash = valueBeforeCursor.lastIndexOf('/');
    const valueBeforeLastSlash = valueBeforeCursor.slice(0, lastIndexOfSlash + 1);
    const startsWithSlash = strings_1.startsWith(valueBeforeCursor, '/');
    let parentDir;
    if (startsWithSlash) {
        if (!root) {
            return [];
        }
        parentDir = path.resolve(root, '.' + valueBeforeLastSlash);
    }
    else {
        parentDir = path.resolve(activeDocFsPath, '..', valueBeforeLastSlash);
    }
    try {
        const paths = fs.readdirSync(parentDir).map(f => {
            return isDir(path.resolve(parentDir, f))
                ? f + '/'
                : f;
        });
        return paths.filter(p => p[0] !== '.');
    }
    catch (e) {
        return [];
    }
}
function isDir(p) {
    try {
        return fs.statSync(p).isDirectory();
    }
    catch (e) {
        return false;
    }
}
function pathToSuggestion(p, valueBeforeCursor, fullValue, range) {
    const isDir = p[p.length - 1] === '/';
    let replaceRange;
    const lastIndexOfSlash = valueBeforeCursor.lastIndexOf('/');
    if (lastIndexOfSlash === -1) {
        replaceRange = shiftRange(range, 1, -1);
    }
    else {
        const valueAfterLastSlash = fullValue.slice(lastIndexOfSlash + 1);
        const startPos = shiftPosition(range.end, -1 - valueAfterLastSlash.length);
        const whitespaceIndex = valueAfterLastSlash.indexOf(' ');
        let endPos;
        if (whitespaceIndex !== -1) {
            endPos = shiftPosition(startPos, whitespaceIndex);
        }
        else {
            endPos = shiftPosition(range.end, -1);
        }
        replaceRange = languageModes_1.Range.create(startPos, endPos);
    }
    if (isDir) {
        return {
            label: p,
            kind: languageModes_1.CompletionItemKind.Folder,
            textEdit: languageModes_1.TextEdit.replace(replaceRange, p),
            command: {
                title: 'Suggest',
                command: 'editor.action.triggerSuggest'
            }
        };
    }
    else {
        return {
            label: p,
            kind: languageModes_1.CompletionItemKind.File,
            textEdit: languageModes_1.TextEdit.replace(replaceRange, p)
        };
    }
}
function resolveWorkspaceRoot(activeDoc, workspaceFolders) {
    for (const folder of workspaceFolders) {
        if (strings_1.startsWith(activeDoc.uri, folder.uri)) {
            return path.resolve(vscode_uri_1.URI.parse(folder.uri).fsPath);
        }
    }
    return undefined;
}
function shiftPosition(pos, offset) {
    return languageModes_1.Position.create(pos.line, pos.character + offset);
}
function shiftRange(range, startOffset, endOffset) {
    const start = shiftPosition(range.start, startOffset);
    const end = shiftPosition(range.end, endOffset);
    return languageModes_1.Range.create(start, end);
}
const PATH_TAG_AND_ATTR = {
    a: 'href',
    area: 'href',
    body: 'background',
    del: 'cite',
    form: 'action',
    frame: ['src', 'longdesc'],
    img: ['src', 'longdesc'],
    ins: 'cite',
    link: 'href',
    object: 'data',
    q: 'cite',
    script: 'src',
    audio: 'src',
    button: 'formaction',
    command: 'icon',
    embed: 'src',
    html: 'manifest',
    input: ['src', 'formaction'],
    source: 'src',
    track: 'src',
    video: ['src', 'poster']
};
