"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.createTempUpdateFile = createTempUpdateFile;
exports.DownloadedUpdateHelper = void 0;

function _bluebirdLst() {
  const data = require("bluebird-lst");

  _bluebirdLst = function () {
    return data;
  };

  return data;
}

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

  _crypto = function () {
    return data;
  };

  return data;
}

function _fs() {
  const data = require("fs");

  _fs = function () {
    return data;
  };

  return data;
}

function _lodash() {
  const data = _interopRequireDefault(require("lodash.isequal"));

  _lodash = function () {
    return data;
  };

  return data;
}

function _fsExtraP() {
  const data = require("fs-extra-p");

  _fsExtraP = function () {
    return data;
  };

  return data;
}

var path = _interopRequireWildcard(require("path"));

function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }

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

/** @private **/
class DownloadedUpdateHelper {
  constructor(cacheDir) {
    this.cacheDir = cacheDir;
    this._file = null;
    this._packageFile = null;
    this.versionInfo = null;
    this.fileInfo = null;
    this._downloadedFileInfo = null;
  }

  get downloadedFileInfo() {
    return this._downloadedFileInfo;
  }

  get file() {
    return this._file;
  }

  get packageFile() {
    return this._packageFile;
  }

  get cacheDirForPendingUpdate() {
    return path.join(this.cacheDir, "pending");
  }

  validateDownloadedPath(updateFile, updateInfo, fileInfo, logger) {
    var _this = this;

    return (0, _bluebirdLst().coroutine)(function* () {
      if (_this.versionInfo != null && _this.file === updateFile && _this.fileInfo != null) {
        // update has already been downloaded from this running instance
        // check here only existence, not checksum
        if ((0, _lodash().default)(_this.versionInfo, updateInfo) && (0, _lodash().default)(_this.fileInfo.info, fileInfo.info) && (yield (0, _fsExtraP().pathExists)(updateFile))) {
          return updateFile;
        } else {
          return null;
        }
      } // update has already been downloaded from some previous app launch


      const cachedUpdateFile = yield _this.getValidCachedUpdateFile(fileInfo, logger);

      if (cachedUpdateFile == null) {
        return null;
      }

      logger.info(`Update has already been downloaded to ${updateFile}).`);
      _this._file = cachedUpdateFile;
      return cachedUpdateFile;
    })();
  }

  setDownloadedFile(downloadedFile, packageFile, versionInfo, fileInfo, updateFileName, isSaveCache) {
    var _this2 = this;

    return (0, _bluebirdLst().coroutine)(function* () {
      _this2._file = downloadedFile;
      _this2._packageFile = packageFile;
      _this2.versionInfo = versionInfo;
      _this2.fileInfo = fileInfo;
      _this2._downloadedFileInfo = {
        fileName: updateFileName,
        sha512: fileInfo.info.sha512,
        isAdminRightsRequired: fileInfo.info.isAdminRightsRequired === true
      };

      if (isSaveCache) {
        yield (0, _fsExtraP().outputJson)(_this2.getUpdateInfoFile(), _this2._downloadedFileInfo);
      }
    })();
  }

  clear() {
    var _this3 = this;

    return (0, _bluebirdLst().coroutine)(function* () {
      _this3._file = null;
      _this3._packageFile = null;
      _this3.versionInfo = null;
      _this3.fileInfo = null;
      yield _this3.cleanCacheDirForPendingUpdate();
    })();
  }

  cleanCacheDirForPendingUpdate() {
    var _this4 = this;

    return (0, _bluebirdLst().coroutine)(function* () {
      try {
        // remove stale data
        yield (0, _fsExtraP().emptyDir)(_this4.cacheDirForPendingUpdate);
      } catch (ignore) {// ignore
      }
    })();
  }

  getValidCachedUpdateFile(fileInfo, logger) {
    var _this5 = this;

    return (0, _bluebirdLst().coroutine)(function* () {
      let cachedInfo;

      const updateInfoFile = _this5.getUpdateInfoFile();

      try {
        cachedInfo = yield (0, _fsExtraP().readJson)(updateInfoFile);
      } catch (e) {
        let message = `No cached update info available`;

        if (e.code !== "ENOENT") {
          yield _this5.cleanCacheDirForPendingUpdate();
          message += ` (error on read: ${e.message})`;
        }

        logger.info(message);
        return null;
      }

      if (cachedInfo.fileName == null) {
        logger.warn(`Cached update info is corrupted: no fileName, directory for cached update will be cleaned`);
        yield _this5.cleanCacheDirForPendingUpdate();
        return null;
      }

      if (fileInfo.info.sha512 !== cachedInfo.sha512) {
        logger.info(`Cached update sha512 checksum doesn't match the latest available update. New update must be downloaded. Cached: ${cachedInfo.sha512}, expected: ${fileInfo.info.sha512}. Directory for cached update will be cleaned`);
        yield _this5.cleanCacheDirForPendingUpdate();
        return null;
      }

      const updateFile = path.join(_this5.cacheDirForPendingUpdate, cachedInfo.fileName);

      if (!(yield (0, _fsExtraP().pathExists)(updateFile))) {
        logger.info("Cached update file doesn't exist, directory for cached update will be cleaned");
        yield _this5.cleanCacheDirForPendingUpdate();
        return null;
      }

      const sha512 = yield hashFile(updateFile);

      if (fileInfo.info.sha512 !== sha512) {
        logger.warn(`Sha512 checksum doesn't match the latest available update. New update must be downloaded. Cached: ${sha512}, expected: ${fileInfo.info.sha512}`);
        yield _this5.cleanCacheDirForPendingUpdate();
        return null;
      }

      _this5._downloadedFileInfo = cachedInfo;
      return updateFile;
    })();
  }

  getUpdateInfoFile() {
    return path.join(this.cacheDirForPendingUpdate, "update-info.json");
  }

}

exports.DownloadedUpdateHelper = DownloadedUpdateHelper;

function hashFile(file, algorithm = "sha512", encoding = "base64", options) {
  return new Promise((resolve, reject) => {
    const hash = (0, _crypto().createHash)(algorithm);
    hash.on("error", reject).setEncoding(encoding);
    (0, _fs().createReadStream)(file, Object.assign({}, options, {
      highWaterMark: 1024 * 1024
      /* better to use more memory but hash faster */

    })).on("error", reject).on("end", () => {
      hash.end();
      resolve(hash.read());
    }).pipe(hash, {
      end: false
    });
  });
}

function createTempUpdateFile(_x, _x2, _x3) {
  return _createTempUpdateFile.apply(this, arguments);
} function _createTempUpdateFile() {
  _createTempUpdateFile = (0, _bluebirdLst().coroutine)(function* (name, cacheDir, log) {
    // https://github.com/electron-userland/electron-builder/pull/2474#issuecomment-366481912
    let nameCounter = 0;
    let result = path.join(cacheDir, name);

    for (let i = 0; i < 3; i++) {
      try {
        yield (0, _fsExtraP().unlink)(result);
        return result;
      } catch (e) {
        if (e.code === "ENOENT") {
          return result;
        }

        log.warn(`Error on remove temp update file: ${e}`);
        result = path.join(cacheDir, `${nameCounter++}-${name}`);
      }
    }

    return result;
  });
  return _createTempUpdateFile.apply(this, arguments);
}
// __ts-babel@6.0.4
//# sourceMappingURL=DownloadedUpdateHelper.js.map