"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.addTags = addTags;
exports.removeTags = removeTags;
exports.clearTags = clearTags;
const coc_nvim_1 = require("coc.nvim");
const vscode_uri_1 = require("vscode-uri");
const tools_1 = require("./tools");
const binaries_1 = require("../binaries");
////////////////////////////////////////////////////////////////////////////////
async function addTags(document, params = {}) {
    const config = coc_nvim_1.workspace.getConfiguration().get('go.tags', {});
    let tags = (params.tags && params.tags.length > 0)
        ? params.tags.join(',')
        : (config.tags || 'json');
    let options = (config.options || config.options === "")
        ? config.options
        : 'json=omitempty';
    const transform = (config.transform || "snakecase");
    const skipUnexported = config.skipUnexported;
    let cursor;
    if (params.prompt) {
        cursor = await coc_nvim_1.window.getCursorPosition();
        tags = await coc_nvim_1.window.requestInput('Enter comma separated tag names', tags);
        if (!tags) {
            return;
        }
        options = await coc_nvim_1.window.requestInput('Enter comma separated options', options);
    }
    const args = [
        '-add-tags', tags.replace(/ +/g, ''),
        '-override',
        '-add-options', (options || ""),
        '-transform', transform,
        ...(await offsetArgs(document, (params.selection || "struct"), cursor))
    ];
    if (skipUnexported) {
        args.push('--skip-unexported');
    }
    await runGomodifytags(document, args);
}
async function removeTags(document, params = {}) {
    const config = coc_nvim_1.workspace.getConfiguration().get('go.tags', {});
    let tags = (params.tags && params.tags.length > 0)
        ? params.tags.join(',')
        : (config.tags || 'json');
    let cursor;
    if (params.prompt) {
        cursor = await coc_nvim_1.window.getCursorPosition();
        tags = await coc_nvim_1.window.requestInput('Enter comma separated tag names', tags);
        if (!tags) {
            return;
        }
    }
    await runGomodifytags(document, [
        '-remove-tags', (tags || "json"),
        '-clear-options',
        ...(await offsetArgs(document, (params.selection || "struct"), cursor))
    ]);
}
async function clearTags(document, params = {}) {
    await runGomodifytags(document, [
        '-clear-tags',
        '-clear-options',
        ...(await offsetArgs(document, (params.selection || "struct")))
    ]);
}
////////////////////////////////////////////////////////////////////////////////
async function runGomodifytags(document, args) {
    const fileName = vscode_uri_1.URI.parse(document.uri).fsPath;
    args.push('-modified', '-file', fileName, '-format', 'json');
    const input = fileArchive(fileName, document.getText());
    const edit = await execGomodifytags(args, input);
    await coc_nvim_1.workspace.applyEdit({ changes: { [document.uri]: [edit] } });
}
async function execGomodifytags(args, input) {
    try {
        const stdout = await (0, tools_1.execTool)(binaries_1.GOMODIFYTAGS, args, input);
        const mods = JSON.parse(stdout);
        return {
            range: {
                start: { line: mods.start - 1, character: 0 },
                end: { line: mods.end, character: 0 }
            },
            newText: mods.lines.join("\n") + "\n"
        };
    }
    catch (err) {
        coc_nvim_1.window.showMessage(`Cannot modify tags: ${err}`, 'error');
        throw err;
    }
}
function fileArchive(fileName, fileContents) {
    return fileName + '\n' + Buffer.byteLength(fileContents, 'utf8') + '\n' + fileContents;
}
// https://github.com/golang/vscode-go/blob/master/src/util.ts#L84
function byteOffsetAt(document, position) {
    const offset = document.offsetAt(position);
    const text = document.getText();
    return Buffer.byteLength(text.substr(0, offset)).toString();
}
async function offsetArgs(document, selection, cursor = null) {
    cursor = cursor || await coc_nvim_1.window.getCursorPosition();
    coc_nvim_1.window.showMessage(`selection = ${selection}`);
    switch (selection) {
        case "struct":
            return ['-offset', byteOffsetAt(document, cursor)];
        case "line":
            return ['-line', String(cursor.line + 1)];
    }
}
//# sourceMappingURL=modify-tags.js.map