import path from 'path';
import defaultBuilder from './build.js';
import { isErrorWithCode, UsageError, WebExtError } from '../errors.js';
import { prepareArtifactsDir } from '../util/artifacts.js';
import { createLogger } from '../util/logger.js';
import getValidatedManifest, { getManifestId } from '../util/manifest.js';
import { defaultAsyncFsReadFile, signAddon as defaultSubmitAddonSigner } from '../util/submit-addon.js';
import { withTempDir } from '../util/temp-dir.js';
const log = createLogger(import.meta.url);
export const extensionIdFile = '.web-extension-id';
export const uploadUuidFile = '.amo-upload-uuid';

// Sign command types and implementation.

export default function sign({
  amoBaseUrl,
  apiKey,
  apiProxy,
  apiSecret,
  artifactsDir,
  ignoreFiles = [],
  sourceDir,
  timeout,
  approvalTimeout,
  channel,
  amoMetadata,
  uploadSourceCode,
  webextVersion
}, {
  build = defaultBuilder,
  preValidatedManifest,
  submitAddon = defaultSubmitAddonSigner,
  asyncFsReadFile = defaultAsyncFsReadFile
} = {}) {
  return withTempDir(async function (tmpDir) {
    await prepareArtifactsDir(artifactsDir);
    let manifestData;
    const savedIdPath = path.join(sourceDir, extensionIdFile);
    const savedUploadUuidPath = path.join(sourceDir, uploadUuidFile);
    if (preValidatedManifest) {
      manifestData = preValidatedManifest;
    } else {
      manifestData = await getValidatedManifest(sourceDir);
    }
    const [buildResult, idFromSourceDir] = await Promise.all([build({
      sourceDir,
      ignoreFiles,
      artifactsDir: tmpDir.path()
    }, {
      manifestData,
      showReadyMessage: false
    }), getIdFromFile(savedIdPath)]);
    const id = getManifestId(manifestData);
    if (idFromSourceDir && !id) {
      throw new UsageError('Cannot use previously auto-generated extension ID ' + `${idFromSourceDir} - This extension ID must be specified in the manifest.json file.`);
    }
    if (!id) {
      // We only auto-generate add-on IDs for MV2 add-ons on AMO.
      if (manifestData.manifest_version !== 2) {
        throw new UsageError('An extension ID must be specified in the manifest.json file.');
      }
      log.warn('No extension ID specified (it will be auto-generated the first time)');
    }
    if (!channel) {
      throw new UsageError('You must specify a channel');
    }
    let metaDataJson;
    if (amoMetadata) {
      const metadataFileBuffer = await asyncFsReadFile(amoMetadata);
      try {
        metaDataJson = JSON.parse(metadataFileBuffer.toString());
      } catch (err) {
        throw new UsageError('Invalid JSON in listing metadata');
      }
    }
    const userAgentString = `web-ext/${webextVersion}`;
    const signSubmitArgs = {
      apiKey,
      apiSecret,
      apiProxy,
      id,
      xpiPath: buildResult.extensionPath,
      downloadDir: artifactsDir,
      channel
    };
    try {
      const result = await submitAddon({
        ...signSubmitArgs,
        amoBaseUrl,
        channel,
        savedIdPath,
        savedUploadUuidPath,
        metaDataJson,
        userAgentString,
        validationCheckTimeout: timeout,
        approvalCheckTimeout: approvalTimeout !== undefined ? approvalTimeout : timeout,
        submissionSource: uploadSourceCode
      });
      return result;
    } catch (clientError) {
      throw new WebExtError(clientError.message);
    }
  });
}
export async function getIdFromFile(filePath, asyncFsReadFile = defaultAsyncFsReadFile) {
  let content;
  try {
    content = await asyncFsReadFile(filePath);
  } catch (error) {
    if (isErrorWithCode('ENOENT', error)) {
      log.debug(`No ID file found at: ${filePath}`);
      return;
    }
    throw error;
  }
  let lines = content.toString().split('\n');
  lines = lines.filter(line => {
    line = line.trim();
    if (line && !line.startsWith('#')) {
      return line;
    }
  });
  const id = lines[0];
  log.debug(`Found extension ID ${id} in ${filePath}`);
  if (!id) {
    throw new UsageError(`No ID found in extension ID file ${filePath}`);
  }
  return id;
}
//# sourceMappingURL=sign.js.map