<reponame>ratte317/mysite5
"use strict";

const crypto = require(`crypto`);

const {
  resolve,
  parse
} = require(`path`);

const axios = require(`axios`);

const {
  pathExists,
  createWriteStream
} = require(`fs-extra`);

const inFlightImageCache = new Map();

module.exports = async function cacheImage(store, image, options) {
  const program = store.getState().program;
  const CACHE_DIR = resolve(`${program.directory}/.cache/contentful/assets/`);
  const {
    file: {
      url,
      fileName,
      details
    }
  } = image;
  const {
    width,
    height,
    maxWidth,
    maxHeight,
    resizingBehavior,
    cropFocus,
    background
  } = options;
  const userWidth = maxWidth || width;
  const userHeight = maxHeight || height;
  const aspectRatio = details.image.height / details.image.width;
  const resultingWidth = Math.round(userWidth || 800);
  const resultingHeight = Math.round(userHeight || resultingWidth * aspectRatio);
  const params = [`w=${resultingWidth}`, `h=${resultingHeight}`];

  if (resizingBehavior) {
    params.push(`fit=${resizingBehavior}`);
  }

  if (cropFocus) {
    params.push(`crop=${cropFocus}`);
  }

  if (background) {
    params.push(`bg=${background}`);
  }

  const optionsHash = crypto.createHash(`md5`).update(JSON.stringify([url, ...params])).digest(`hex`);
  const {
    name,
    ext
  } = parse(fileName);
  const absolutePath = resolve(CACHE_DIR, `${name}-${optionsHash}${ext}`); // Query the filesystem for file existence

  const alreadyExists = await pathExists(absolutePath); // Whether the file exists or not, if we are downloading it then await

  const inFlight = inFlightImageCache.get(absolutePath);

  if (inFlight) {
    await inFlight;
  } else if (!alreadyExists) {
    // File doesn't exist and is not being download yet
    const downloadPromise = new Promise(async (resolve, reject) => {
      const previewUrl = `http:${url}?${params.join(`&`)}`;
      const response = await axios({
        method: `get`,
        url: previewUrl,
        responseType: `stream`
      });
      const file = createWriteStream(absolutePath);
      response.data.pipe(file);
      file.on(`finish`, resolve);
      file.on(`error`, reject);
    });
    inFlightImageCache.set(absolutePath, downloadPromise);
    await downloadPromise; // When the file is downloaded, remove the promise from the cache

    inFlightImageCache.delete(absolutePath);
  } // Now the file should be completely downloaded


  return absolutePath;
};