"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

// src/extension.ts
var extension_exports = {};
__export(extension_exports, {
  activate: () => activate,
  deactivate: () => deactivate
});
module.exports = __toCommonJS(extension_exports);
var import_coc3 = require("coc.nvim");
var import_node_process = __toESM(require("process"));

// src/commands.ts
var import_coc2 = require("coc.nvim");

// src/constants.ts
var EXTENSION_NS = "deno";

// src/lsp_extensions.ts
var import_coc = require("coc.nvim");
var registryState = new import_coc.NotificationType(
  "deno/registryState"
);
var task = new import_coc.RequestType0(
  "deno/task"
);
var virtualTextDocument = new import_coc.RequestType("deno/virtualTextDocument");

// src/commands.ts
var terminal;
function cacheActiveDocument() {
  return async () => {
    const { document } = await import_coc2.workspace.getCurrentState();
    return import_coc2.window.withProgress({
      title: "caching"
    }, () => {
      return import_coc2.commands.executeCommand(
        "deno.cache",
        [document.uri.toString()],
        document.uri.toString()
      );
    });
  };
}
async function doInitialize() {
  const title = "Initialize Deno Project";
  const linting = "Enable Deno linting?";
  const unstable = "Enable Deno unstable APIs?";
  const prettier = "Disable coc-prettier for current project?";
  const items = [linting, unstable];
  if (import_coc2.extensions.all.find((e) => e.id === "coc-prettier")) {
    items.push(prettier);
  }
  const settings = await import_coc2.window.showPickerDialog(items, title);
  if (!settings) return;
  const config = import_coc2.workspace.getConfiguration(EXTENSION_NS);
  config.update("enable", true);
  config.update("lint", settings.includes(linting));
  config.update("unstable", settings.includes(unstable));
  if (settings.includes(prettier)) {
    const prettierConfig = import_coc2.workspace.getConfiguration("prettier");
    prettierConfig.update("disableLanguages", ["typescript", "javascript"]);
  }
  import_coc2.window.showInformationMessage("Deno is now setup in this workspace.");
}
function initializeWorkspace() {
  return async () => {
    await doInitialize();
    await checkTSServer();
  };
}
function showReferences(uri, position, locations) {
  if (!uri) return;
  import_coc2.commands.executeCommand(
    "editor.action.showReferences",
    import_coc2.Uri.parse(uri),
    position,
    locations
  );
}
function status(_context, client2) {
  return async () => {
    const content = await client2.sendRequest(virtualTextDocument, {
      textDocument: { uri: "deno:/status.md" }
    });
    if (!content) return;
    const nvim = import_coc2.workspace.nvim;
    nvim.pauseNotification();
    nvim.command(
      `edit +setl\\ buftype=nofile [Deno Language Server Status]`,
      true
    );
    nvim.command("setl nobuflisted bufhidden=wipe", true);
    nvim.command("setl filetype=markdown", true);
    nvim.call("append", [0, content.split("\n")], true);
    nvim.command(`exe 1`, true);
    await nvim.resumeNotification();
  };
}
function task2(_context, client2) {
  return async () => {
    const tasks = await client2.sendRequest(task);
    if (!tasks || tasks.length === 0) return;
    const items = [...tasks.map((task4) => ({ text: task4.detail }))];
    const idx = await import_coc2.window.showMenuPicker(items, {
      title: "Select a task to run",
      position: "center"
    });
    if (idx === -1) return;
    if (terminal) {
      terminal.dispose();
      terminal = void 0;
    }
    const task3 = tasks[idx];
    terminal = await import_coc2.window.createTerminal({
      name: task3.name,
      cwd: import_coc2.workspace.root
    });
    terminal.sendText(task3.detail);
  };
}
async function test(uri, name) {
  const config = import_coc2.workspace.getConfiguration(EXTENSION_NS);
  const testArgs = [...config.get("codeLens.testArgs", [])];
  if (config.has("unstable")) {
    testArgs.push("--unstable");
  }
  if (!testArgs.includes("--import-map")) {
    const importMap = config.get("importMap");
    if (importMap == null ? void 0 : importMap.trim()) {
      testArgs.push("--import-map", importMap.trim());
    }
  }
  const env = config.has("cache") ? { "DENO_DIR": config.get("cache") } : void 0;
  const bin = config.get("path", "deno");
  const filter = new RegExp(
    "^" + name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") + "$"
  );
  const args = [
    "test",
    ...testArgs,
    "--filter",
    `"${filter}"`,
    import_coc2.Uri.parse(uri).fsPath
  ];
  if (terminal) {
    terminal.dispose();
    terminal = void 0;
  }
  terminal = await import_coc2.window.createTerminal({ name, cwd: import_coc2.workspace.root, env });
  terminal.sendText(`${bin} ${args.join(" ")}`);
}
function restart(_context, client2) {
  return () => {
    if (client2.getPublicState() === import_coc2.State.Running) {
      client2.restart();
    }
  };
}
async function checkTSServer() {
  const tsserverConfig = import_coc2.workspace.getConfiguration("tsserver");
  const enable = tsserverConfig.get("enable");
  if (enable) {
    tsserverConfig.update("enable", false);
  }
}

// src/extension.ts
function assert(cond, msg = "Assertion failed.") {
  if (!cond) {
    throw new Error(msg);
  }
}
var settingsKeys = [
  "cache",
  "cacheOnSave",
  "codeLens",
  "config",
  "enable",
  "importMap",
  "inlayHints",
  "internalDebug",
  "lint",
  "suggest",
  "unstable"
];
function getSettings() {
  const settings = import_coc3.workspace.getConfiguration(EXTENSION_NS);
  const result = /* @__PURE__ */ Object.create(null);
  for (const key of settingsKeys) {
    const value = settings.inspect(key);
    assert(value);
    result[key] = value.workspaceFolderValue ?? value.workspaceValue ?? value.globalValue ?? value.defaultValue;
  }
  return result;
}
var client;
var serverVersion = "";
var DenoTextDocumentContentProvider = class {
  constructor(client2) {
    this.client = client2;
  }
  provideTextDocumentContent(uri, token) {
    return this.client.sendRequest(
      virtualTextDocument,
      { textDocument: { uri: uri.toString() } },
      token
    );
  }
};
async function tryActivate(context) {
  var _a, _b;
  await checkTSServer();
  const command = import_coc3.workspace.getConfiguration(EXTENSION_NS).get("path", "deno");
  const run = {
    command,
    args: ["lsp"],
    options: { env: { ...import_node_process.default.env, "NO_COLOR": true } }
  };
  const clientOptions = {
    documentSelector: [
      { scheme: "file", language: "json" },
      { scheme: "file", language: "jsonc" },
      { scheme: "file", language: "markdown" },
      { scheme: "file", language: "javascript" },
      { scheme: "file", language: "javascriptreact" },
      { scheme: "file", language: "typescript" },
      { scheme: "file", language: "typescriptreact" },
      { scheme: "deno", language: "javascript" },
      { scheme: "deno", language: "javascriptreact" },
      { scheme: "deno", language: "typescript" },
      { scheme: "deno", language: "typescriptreact" }
    ],
    diagnosticCollectionName: EXTENSION_NS,
    initializationOptions: getSettings(),
    middleware: {
      didOpen: async (data, next) => {
        const fsPath = import_coc3.Uri.parse(data.uri).fsPath;
        if (fsPath.includes("deno:asset") || fsPath.includes("deno:/asset")) {
          return;
        }
        if (fsPath.includes("deno:/https")) {
          const pwd = import_node_process.default.cwd() + "/";
          data.uri = import_coc3.Uri.parse(fsPath.replace(pwd, "")).toString();
        }
        await next(data);
      }
    }
  };
  client = new import_coc3.LanguageClient(
    EXTENSION_NS,
    run,
    clientOptions
  );
  context.subscriptions.push(import_coc3.services.registLanguageClient(client));
  const statusBarItem = import_coc3.window.createStatusBarItem(0);
  context.subscriptions.push(statusBarItem);
  context.subscriptions.push(
    import_coc3.workspace.onDidChangeConfiguration((evt) => {
      if (evt.affectsConfiguration(EXTENSION_NS)) {
        client.sendNotification(
          "workspace/didChangeConfiguration",
          // We actually set this to empty because the language server will
          // call back and get the configuration. There can be issues with the
          // information on the event not being reliable.
          { settings: null }
        );
      }
    }),
    // Register a content provider for Deno resolved read-only files.
    import_coc3.workspace.registerTextDocumentContentProvider(
      EXTENSION_NS,
      new DenoTextDocumentContentProvider(client)
    )
  );
  const registerCommand = createRegisterCommand(context);
  registerCommand("task", task2);
  registerCommand("status", status);
  registerCommand("restart", restart);
  registerCommand("cacheActiveDocument", cacheActiveDocument);
  registerCommand("initializeWorkspace", initializeWorkspace);
  import_coc3.commands.registerCommand(`${EXTENSION_NS}.test`, test, null, true);
  import_coc3.commands.registerCommand(
    `${EXTENSION_NS}.showReferences`,
    showReferences,
    null,
    true
  );
  await client.onReady();
  client.onNotification(registryState, createRegistryStateHandler());
  serverVersion = (((_b = (_a = client.initializeResult) == null ? void 0 : _a.serverInfo) == null ? void 0 : _b.version) ?? "").split(" ")[0];
  if (serverVersion) {
    statusBarItem.text = `Deno ${serverVersion}`;
    statusBarItem.show();
  }
}
async function activate(context) {
  const enable = import_coc3.workspace.getConfiguration(EXTENSION_NS).get("enable", false);
  if (!enable) {
    context.subscriptions.push(
      import_coc3.commands.registerCommand(
        `${EXTENSION_NS}.initializeWorkspace`,
        async () => {
          await doInitialize();
          await tryActivate(context);
        }
      )
    );
    return;
  }
  await tryActivate(context);
}
function deactivate() {
  return client == null ? void 0 : client.stop();
}
function createRegisterCommand(context) {
  return function registerCommand(name, factory) {
    const fullName = `${EXTENSION_NS}.${name}`;
    const command = factory(context, client);
    context.subscriptions.push(import_coc3.commands.registerCommand(fullName, command));
  };
}
function createRegistryStateHandler() {
  return async function handler(p) {
    if (p.suggestions) {
      const selection = await import_coc3.window.showInformationMessage(
        `The server "${p.origin}" supports completion suggestions for imports. Do you wish to enable this? (Only do this if you trust "${p.origin}") [Learn More](https://github.com/denoland/vscode_deno/blob/main/docs/ImportCompletions.md)`,
        "No",
        "Enable"
      );
      const enable = selection === "Enable";
      const config = import_coc3.workspace.getConfiguration("deno.suggest.imports");
      const hosts = config.get("hosts", {});
      hosts[p.origin] = enable;
      config.update("hosts", hosts);
    }
  };
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  activate,
  deactivate
});
