"use strict";

var _WeakMap = require("@babel/runtime-corejs2/core-js/weak-map");
var _Object$defineProperty = require("@babel/runtime-corejs2/core-js/object/define-property");
var _Object$getOwnPropertyDescriptor = require("@babel/runtime-corejs2/core-js/object/get-own-property-descriptor");
var _interopRequireDefault = require("@babel/runtime-corejs2/helpers/interopRequireDefault");
_Object$defineProperty(exports, "__esModule", {
  value: true
});
exports.default = zipPack;
var _promise = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/promise"));
var _path = _interopRequireDefault(require("path"));
var _index = require("../../cli-shared-utils/index.js");
var paths = _interopRequireWildcard(require("../lib/paths.js"));
var _constanst = require("../lib/constanst.js");
var _readdir = _interopRequireWildcard(require("../lib/readdir.js"));
var _rpk = _interopRequireDefault(require("../lib/rpk.js"));
var _nodeForge = _interopRequireDefault(require("node-forge"));
function _getRequireWildcardCache(e) { if ("function" != typeof _WeakMap) return null; var r = new _WeakMap(), t = new _WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = _Object$defineProperty && _Object$getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? _Object$getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? _Object$defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
// 生成签名文件
async function generateReleaseSign(signFile, packageName) {
  const cachePath = _path.default.join(__dirname, '../../../node_modules', packageName);

  // 判断本地是否有缓存
  try {
    const privateFile = _path.default.join(cachePath, 'private.pem');
    const certificateFile = _path.default.join(cachePath, 'certificate.pem');
    if (_index.fs.existsSync(privateFile) && _index.fs.existsSync(certificateFile)) {
      (0, _index.info)(`\n####检测到${cachePath}路径下有release签名缓存####`);

      // 自动使用缓存
      _index.fs.copySync(privateFile, signFile.privatekey);
      _index.fs.copySync(certificateFile, signFile.certificate);
      return;
    }
  } catch (err) {
    console.error(err);
  }
  // 使用rl.question()方法从命令行读取证书请求参数
  (0, _index.info)('\n本地检测到未包含release签名，正在生成release签名信息...');
  const organizationName = packageName;

  // 使用包名作为名称
  const commonName = packageName;
  const countryName = 'CN';
  const stateName = 'ZJ';
  const localityName = 'HZ';

  // 生成RSA密钥对
  const keys = _nodeForge.default.pki.rsa.generateKeyPair(2048);

  // 创建证书
  const cert = _nodeForge.default.pki.createCertificate();
  cert.publicKey = keys.publicKey;
  cert.serialNumber = '01';
  cert.validity.notBefore = new Date();
  cert.validity.notAfter = new Date();
  cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 10);
  const certObj = [{
    name: 'commonName',
    value: commonName
  }, {
    name: 'countryName',
    value: countryName
  }, {
    shortName: 'ST',
    value: stateName
  }, {
    name: 'localityName',
    value: localityName
  }, {
    name: 'organizationName',
    value: organizationName
  }, {
    shortName: 'OU',
    value: 'MINIGAME'
  }];
  cert.setSubject(certObj);
  (0, _index.info)('release签名参数为:');
  console.log(certObj);
  cert.setIssuer(cert.subject.attributes);
  cert.setExtensions([{
    name: 'basicConstraints',
    cA: true
  }, {
    name: 'keyUsage',
    digitalSignature: true,
    keyCertSign: true,
    cRLSign: true
  }]);
  cert.sign(keys.privateKey);

  // 将密钥和证书保存到文件中
  const pemPrivateKey = _nodeForge.default.pki.privateKeyToPem(keys.privateKey);
  const pemCertificate = _nodeForge.default.pki.certificateToPem(cert);
  // 如果release路径不存在
  const dirPath = _path.default.dirname(signFile.privatekey);
  if (!_index.fs.existsSync(dirPath)) {
    _index.fs.mkdirSync(dirPath, {
      recursive: true
    });
  }
  (0, _index.info)(`####签名生成成功####，写入签名privatekey：${signFile.privatekey}`);
  _index.fs.writeFileSync(signFile.privatekey, pemPrivateKey);
  (0, _index.info)(`写入签名certificate：${signFile.certificate}\n`);
  _index.fs.writeFileSync(signFile.certificate, pemCertificate);

  // 缓存release签名到本地
  try {
    if (!_index.fs.existsSync(cachePath)) {
      _index.fs.mkdirSync(cachePath, {
        recursive: true
      });
      _index.fs.writeFileSync(_path.default.join(cachePath, 'private.pem'), pemPrivateKey);
      _index.fs.writeFileSync(_path.default.join(cachePath, 'certificate.pem'), pemCertificate);
      (0, _index.info)(`####release签名需要保存好!!!#### 该文件已缓存到：${cachePath}，若忘记签名，可在此路径下查找。`);
    }
  } catch (err) {
    console.error(err);
  }
}
async function zipPack(isRelease, packageName, singlePackage, subpackages, manifest, buildType, compileStartTime) {
  // 签名文件
  const signFiles = {
    debug: {
      privatekey: paths.DEBUG_PRIVATE_KEY,
      certificate: paths.DEBUG_CERTIFICATE
    },
    release: {
      privatekey: paths.RELEASE_PRIVATE_KEY,
      certificate: paths.RELEASE_CERTIFICATE
    }
  };
  // 编译完成开始打包，打包前先校验签名文件是否存在
  const signFile = signFiles[isRelease ? 'release' : 'debug'];
  // debug包的后缀 .rpk  release包的后缀 .signed.rpk
  // buildType 默认值为release
  let RPK_SIGNED_NEW = _constanst.RPK_SIGNED;
  let RPK_NEW = _constanst.RPK;
  if (buildType && !buildType.includes('release')) {
    RPK_SIGNED_NEW = `.${buildType}${_constanst.RPK_SIGNED}`;
    RPK_NEW = `.${buildType}${_constanst.RPK}`;
  }
  const ext = isRelease ? RPK_SIGNED_NEW : RPK_NEW;

  /**
   * 如果本地不存在release签名文件，则自动帮助cp生成release签名文件
   */
  if (isRelease) {
    if (!_index.fs.existsSync(signFile.privatekey) || !_index.fs.existsSync(signFile.certificate)) {
      await generateReleaseSign(signFile, packageName);
    }
  }
  if (!_index.fs.existsSync(signFile.privatekey)) {
    throw new Error(`${_constanst.LOG_TITLE}缺少私钥文件, 打包失败: ${signFile.privatekey}`);
  }
  if (!_index.fs.existsSync(signFile.certificate)) {
    throw new Error(`${_constanst.LOG_TITLE}缺少证书文件, 打包失败: ${signFile.certificate}`);
  }
  return new _promise.default(resolve => {
    (0, _index.info)(`${_constanst.LOG_TITLE}${singlePackage ? '原整包编译完成，开始生成原整包' : '分包编译完成，开始生成分包'} 耗时：${new Date().valueOf() - compileStartTime}ms`);

    // 遍历出build目录所有文件
    const files = (0, _readdir.default)(paths.BUILD, isRelease ? _readdir.noDotSymbolsFiles : _readdir.noDotFiles);

    // 如果是打原整包
    if (singlePackage) {
      // 打原整包到temp目录 有插件包的也走这个逻辑，因为需要打个兼容的包
      (0, _rpk.default)(`${packageName}${_constanst.RPK}`, files, paths.BUILD, paths.TEMP, signFile, manifest).then(resolve);
    } else {
      // 如果存在分包，那么就打出各个分包，并和原整包一起再打一个rpk，到dist目录
      const pkgRes = [];
      // 根据分包配置，找到各个包对应的资源。执行如下操作后，files中剩下的即为主包的资源
      subpackages.forEach(({
        name,
        root
      }) => {
        const matchFiles = [];
        for (let index = files.length - 1; index >= 0; index--) {
          const file = files[index];
          const ext = _path.default.extname(root);
          if (isRelease && !(0, _readdir.noDotSymbolsFiles)(file, 0, _path.default.basename(file))) {
            continue;
          }
          if (ext === '' && file.indexOf(root) === 0) {
            // 如果是目录，校验路径
            matchFiles.push(files.splice(index, 1)[0]);
          } else if (ext !== '' && (file === root || file === `${root}.map`)) {
            // 如果是文件，校验是否为 xxx.js 和 xxx.js.map
            matchFiles.push(files.splice(index, 1)[0]);
          }
        }
        pkgRes.push({
          name,
          matchFiles
        });
      });
      // 打各个分包
      const rpkPromise = pkgRes.map(({
        name,
        matchFiles
      }) => {
        return (0, _rpk.default)(`${name}${_constanst.RPK}`, matchFiles, paths.BUILD, paths.TEMP, signFile);
      });
      const promiseArr = [(0, _rpk.default)(`${_constanst.MAIN}${_constanst.RPK}`, files, paths.BUILD, paths.TEMP, signFile, manifest)];

      // 分包都打好后，连原整包一起打一个整包
      _promise.default.all([...rpkPromise, ...promiseArr]).then(function () {
        (0, _rpk.default)(`${packageName}${ext}`, (0, _readdir.default)(paths.TEMP), paths.TEMP, paths.DIST, signFile).then(() => {
          resolve();
        });
      });
    }
  });
}