"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.calculateHash = calculateHash;
exports.optimizeImageAsync = optimizeImageAsync;
exports.hasUnoptimizedAssetsAsync = hasUnoptimizedAssetsAsync;
exports.getAssetFilesAsync = getAssetFilesAsync;
exports.readAssetJsonAsync = readAssetJsonAsync;
exports.createNewFilename = createNewFilename;

function _fsExtra() {
  const data = _interopRequireDefault(require("fs-extra"));

  _fsExtra = function () {
    return data;
  };

  return data;
}

function _path() {
  const data = _interopRequireDefault(require("path"));

  _path = function () {
    return data;
  };

  return data;
}

function _crypto() {
  const data = _interopRequireDefault(require("crypto"));

  _crypto = function () {
    return data;
  };

  return data;
}

function _chalk() {
  const data = _interopRequireDefault(require("chalk"));

  _chalk = function () {
    return data;
  };

  return data;
}

function _glob() {
  const data = _interopRequireDefault(require("glob"));

  _glob = function () {
    return data;
  };

  return data;
}

function _imageUtils() {
  const data = require("@expo/image-utils");

  _imageUtils = function () {
    return data;
  };

  return data;
}

function _jsonFile() {
  const data = _interopRequireDefault(require("@expo/json-file"));

  _jsonFile = function () {
    return data;
  };

  return data;
}

function _config() {
  const data = require("@expo/config");

  _config = function () {
    return data;
  };

  return data;
}

function _tempy() {
  const data = _interopRequireDefault(require("tempy"));

  _tempy = function () {
    return data;
  };

  return data;
}

function _Logger() {
  const data = _interopRequireDefault(require("./Logger"));

  _Logger = function () {
    return data;
  };

  return data;
}

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

/*
 * Calculate SHA256 Checksum value of a file based on its contents
 */
function calculateHash(filePath) {
  const contents = _fsExtra().default.readFileSync(filePath);

  return _crypto().default.createHash('sha256').update(contents).digest('hex');
}
/*
 * Compress an inputted jpg or png
 */


async function optimizeImageAsync(inputPath, quality) {
  _Logger().default.global.info(`Optimizing ${inputPath}`);

  const outputPath = _tempy().default.directory();

  await (0, _imageUtils().sharpAsync)({
    input: inputPath,
    output: outputPath,
    quality
  });
  return _path().default.join(outputPath, _path().default.basename(inputPath));
}

/*
 * Returns a boolean indicating whether or not there are assets to optimize
 */
async function hasUnoptimizedAssetsAsync(projectDir, options) {
  if (!_fsExtra().default.existsSync(_path().default.join(projectDir, '.expo-shared/assets.json'))) {
    return true;
  }

  const {
    selectedFiles
  } = await getAssetFilesAsync(projectDir, options);
  const {
    assetInfo
  } = await readAssetJsonAsync(projectDir);

  for (const file of selectedFiles) {
    const hash = calculateHash(file);

    if (!assetInfo[hash]) {
      return true;
    }
  }

  return false;
}
/*
 * Find all project assets under assetBundlePatterns in app.json excluding node_modules.
 * If --include of --exclude flags were passed in those results are filtered out.
 */


async function getAssetFilesAsync(projectDir, options) {
  const {
    exp
  } = await (0, _config().readConfigJsonAsync)(projectDir);
  const {
    assetBundlePatterns
  } = exp;
  const globOptions = {
    cwd: projectDir,
    ignore: ['**/node_modules/**', '**/ios/**', '**/android/**']
  }; // All files must be returned even if flags are passed in to properly update assets.json

  const allFiles = [];
  const patterns = assetBundlePatterns || ['**/*'];
  patterns.forEach(pattern => {
    allFiles.push(..._glob().default.sync(pattern, globOptions));
  }); // If --include is passed in, only return files matching that pattern

  const included = options && options.include ? [..._glob().default.sync(options.include, globOptions)] : allFiles;
  const toExclude = new Set();

  if (options && options.exclude) {
    _glob().default.sync(options.exclude, globOptions).forEach(file => toExclude.add(file));
  } // If --exclude is passed in, filter out files matching that pattern


  const excluded = included.filter(file => !toExclude.has(file));
  const filtered = options && options.exclude ? excluded : included;
  return {
    allFiles: filterImages(allFiles, projectDir),
    selectedFiles: filterImages(filtered, projectDir)
  };
}
/*
 * Formats an array of files to include the project directory and filters out PNGs and JPGs.
 */


function filterImages(files, projectDir) {
  const regex = /\.(png|jpg|jpeg)$/;
  const withDirectory = files.map(file => `${projectDir}/${file}`.replace('//', '/'));
  const allImages = withDirectory.filter(file => regex.test(file.toLowerCase()));
  return allImages;
}
/*
 * Read the contents of assets.json under .expo-shared folder. Create the file/directory if they don't exist.
 */


async function readAssetJsonAsync(projectDir) {
  const dirPath = _path().default.join(projectDir, '.expo-shared');

  if (!_fsExtra().default.existsSync(dirPath)) {
    _fsExtra().default.mkdirSync(dirPath);
  }

  const assetJson = new (_jsonFile().default)(_path().default.join(dirPath, 'assets.json'));

  if (!_fsExtra().default.existsSync(assetJson.file)) {
    const message = `Creating ${_chalk().default.italic('.expo-shared/assets.json')} in the project's root directory.\n` + `This file is autogenerated and should not be edited directly.\n` + 'You should commit this to git so that asset state is shared between collaborators.';

    _Logger().default.global.info(message);

    await assetJson.writeAsync({});
  }

  const assetInfo = await assetJson.readAsync();
  return {
    assetJson,
    assetInfo
  };
}
/*
 * Add .orig extension to a filename in a path string
 */


function createNewFilename(imagePath) {
  const {
    dir,
    name,
    ext
  } = _path().default.parse(imagePath);

  return _path().default.join(dir, name + '.orig' + ext);
}
//# sourceMappingURL=__sourcemaps__/AssetUtils.js.map