text: "use strict";
  
  var fs = require("fs");
  var os = require("os");
  const { encode: encodeQuery } = require("querystring");
  const { strictEqual } = require("assert");
  const envPaths = require("env-paths");
  const FileCache = require("@derhuerst/http-basic/lib/FileCache").default;
  var ProgressBar = require("progress");
  var request = require("@derhuerst/http-basic");
  var { ffmpegPath } = require(".");
  var pkg = require("./package");
  
  const exitOnError = (err) => {
    console.error(err);
    process.exit(1);
  };
  const warnWith = (msg) => (err) => {
    console.warn(msg);
  };
  
  if (!ffmpegPath) {
    exitOnError(
      "ffmpeg-static-mirror install failed: No binary found for architecture"
    );
  }
  
  try {
    if (fs.statSync(ffmpegPath).isFile()) {
      console.info(
        "ffmpeg-static-mirror reports that ffmpeg is installed already."
      );
      process.exit(0);
    }
  } catch (err) {
    if (err && err.code !== "ENOENT") exitOnError(err);
  }
  
  let agent = false;
  // https://github.com/request/request/blob/a9557c9e7de2c57d92d9bab68a416a87d255cd3d/lib/getProxyFromURI.js#L66-L71
  const proxyUrl =
    process.env.HTTPS_PROXY ||
    process.env.https_proxy ||
    process.env.HTTP_PROXY ||
    process.env.http_proxy;
  if (proxyUrl) {
    const HttpsProxyAgent = require("https-proxy-agent");
    const { hostname, port, protocol } = new URL(proxyUrl);
    agent = new HttpsProxyAgent({ hostname, port, protocol });
  }
  
  // https://advancedweb.hu/how-s3-signed-urls-work/
  const normalizeS3Url = (url) => {
    url = new URL(url);
    if (url.hostname.slice(-17) !== ".s3.amazonaws.com") return url.href;
    const query = Array.from(url.searchParams.entries())
      .filter(([key]) => key.slice(0, 6).toLowerCase() !== "x-amz-")
      .reduce((query, [key, val]) => ({ ...query, [key]: val }), {});
    url.search = encodeQuery(query);
    return url.href;
  };
  strictEqual(
    normalizeS3Url("https://example.org/foo?bar"),
    "https://example.org/foo?bar"
  );
  strictEqual(
    normalizeS3Url(
      "https://github-production-release-asset-2e65be.s3.amazonaws.com/29458513/26341680-4231-11ea-8e36-ae454621d74a?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20200405%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20200405T225358Z&X-Amz-Expires=300&X-Amz-Signature=d6415097af04cf62ea9b69d3c1a421278e96bcb069afa48cf021ec3b6941bae4&X-Amz-SignedHeaders=host&actor_id=0&response-content-disposition=attachment%3B%20filename%3Ddarwin-x64&response-content-type=application%2Foctet-stream"
    ),
    "https://github-production-release-asset-2e65be.s3.amazonaws.com/29458513/26341680-4231-11ea-8e36-ae454621d74a?actor_id=0&response-content-disposition=attachment%3B%20filename%3Ddarwin-x64&response-content-type=application%2Foctet-stream"
  );
  
  const cache = new FileCache(envPaths(pkg.name).cache);
  cache.getCacheKey = (url) => {
    return FileCache.prototype.getCacheKey(normalizeS3Url(url));
  };
  
  const noop = () => {};
  function downloadFile(url, destinationPath, progressCallback = noop) {
    let fulfill, reject;
    let totalBytes = 0;
  
    const promise = new Promise((x, y) => {
      fulfill = x;
      reject = y;
    });
  
    request(
      "GET",
      url,
      {
        agent,
        followRedirects: true,
        maxRedirects: 3,
        gzip: true,
        cache,
        timeout: 30 * 1000, // 30s
        retry: true,
      },
      (err, response) => {
        if (err || response.statusCode !== 200) {
          err = err || new Error("Download failed.");
          if (response) {
            err.url = response.url;
            err.statusCode = response.statusCode;
          }
          reject(err);
          return;
        }
  
        const file = fs.createWriteStream(destinationPath);
        file.on("finish", () => fulfill());
        file.on("error", (error) => reject(error));
        response.body.pipe(file);
  
        if (!response.fromCache && progressCallback) {
          const cLength = response.headers["content-length"];
          totalBytes = cLength ? parseInt(cLength, 10) : null;
          response.body.on("data", (chunk) => {
            progressCallback(chunk.length, totalBytes);
          });
        }
      }
    );
  
    return promise;
  }
  
  let progressBar = null;
  function onProgress(deltaBytes, totalBytes) {
    if (totalBytes === null) return;
    if (!progressBar) {
      progressBar = new ProgressBar(
        `Downloading ffmpeg ${releaseName} [:bar] :percent :etas `,
        {
          complete: "|",
          incomplete: " ",
          width: 20,
          total: totalBytes,
        }
      );
    }
  
    progressBar.tick(deltaBytes);
  }
  
  const release =
    process.env.FFMPEG_BINARY_RELEASE ||
    pkg["ffmpeg-static"]["binary-release-tag"];
  const releaseName = pkg["ffmpeg-static"]["binary-release-name"] || release;
  const arch = process.env.npm_config_arch || os.arch();
  const platform = process.env.npm_config_platform || os.platform();
  const base =
    process.env.THE_BASE_URL ||
    "https://mirror.ghproxy.com/https://github.com/descriptinc/ffmpeg-ffprobe-static/releases/download/";
  console.log(`[ffmpeg-static-mirror] Using base url: ${base}`);
  const baseUrl = new URL(release, base).href;
  const ffmpegUrl = `${baseUrl}/ffmpeg-${platform}-${arch}`;
  const readmeUrl = `${baseUrl}/${platform}-${arch}.README`;
  const licenseUrl = `${baseUrl}/${platform}-${arch}.LICENSE`;
  
  downloadFile(ffmpegUrl, ffmpegPath, onProgress)
    .then(() => {
      fs.chmodSync(ffmpegPath, 0o755); // make executable
    })
    .catch(exitOnError)
  
    .then(() => downloadFile(readmeUrl, `${ffmpegPath}.README`))
    .catch(warnWith("Failed to download the ffmpeg README."))
  
    .then(() => downloadFile(licenseUrl, `${ffmpegPath}.LICENSE`))
    .catch(warnWith("Failed to download the ffmpeg LICENSE."));
  