"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.exportCertBinary = exportCertBinary;
exports.exportCertBase64 = exportCertBase64;
exports.exportPrivateKey = exportPrivateKey;
exports.logKeystoreHashes = logKeystoreHashes;
exports.logKeystoreCredentials = logKeystoreCredentials;
exports.createKeystore = createKeystore;
exports.generateUploadKeystore = generateUploadKeystore;

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

  _path = function () {
    return data;
  };

  return data;
}

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

  _fsExtra = function () {
    return data;
  };

  return data;
}

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

  _chalk = function () {
    return data;
  };

  return data;
}

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

  _crypto = function () {
    return data;
  };

  return data;
}

function _v() {
  const data = _interopRequireDefault(require("uuid/v4"));

  _v = function () {
    return data;
  };

  return data;
}

function _spawnAsync() {
  const data = _interopRequireDefault(require("@expo/spawn-async"));

  _spawnAsync = function () {
    return data;
  };

  return data;
}

function _axios() {
  const data = _interopRequireDefault(require("axios"));

  _axios = function () {
    return data;
  };

  return data;
}

function _progress() {
  const data = _interopRequireDefault(require("progress"));

  _progress = function () {
    return data;
  };

  return data;
}

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

  _Logger = function () {
    return data;
  };

  return data;
}

function _UserSettings() {
  const data = _interopRequireDefault(require("../UserSettings"));

  _UserSettings = function () {
    return data;
  };

  return data;
}

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

const log = _Logger().default.global;

const NEWLINE = process.platform === 'win32' ? '\r\n' : '\n';
const javaExecutable = process.platform === 'win32' ? 'java.exe' : 'java';

async function exportCertBinary({
  keystorePath,
  keystorePassword,
  keyAlias
}, certFile) {
  try {
    return (0, _spawnAsync().default)('keytool', ['-exportcert', '-keystore', keystorePath, '-storepass', keystorePassword, '-alias', keyAlias, '-file', certFile, '-noprompt', '-storetype', 'JKS']);
  } catch (err) {
    if (err.code === 'ENOENT') {
      log.warn('Are you sure you have keytool installed?');
      log.info('keytool is a part of OpenJDK: https://openjdk.java.net/');
      log.info('Also make sure that keytool is in your PATH after installation.');
    }

    throw err;
  }
}

async function exportCertBase64({
  keystorePath,
  keystorePassword,
  keyAlias
}, certFile) {
  try {
    return (0, _spawnAsync().default)('keytool', ['-export', '-rfc', '-keystore', keystorePath, '-storepass', keystorePassword, '-alias', keyAlias, '-file', certFile, '-noprompt', '-storetype', 'JKS']);
  } catch (err) {
    if (err.code === 'ENOENT') {
      log.warn('Are you sure you have keytool installed?');
      log.info('keytool is a part of OpenJDK: https://openjdk.java.net/');
      log.info('Also make sure that keytool is in your PATH after installation.');
    }

    throw err;
  }
}

async function exportPrivateKey({
  keystorePath,
  keystorePassword,
  keyAlias,
  keyPassword
}, encryptionKey, outputPath) {
  let nodePty;
  const ptyTmpDir = '/tmp/pty-tmp-install';

  try {
    // it's not very pretty solution, but we decided to use it because it's affecting only people using
    // this command and if node-pty is supported on that system instalation process will be invisble for user.
    nodePty = require('node-pty-prebuilt');
  } catch (err) {
    try {
      log.info('Installing node-pty-prebuilt in a temporary directory');
      await _fsExtra().default.mkdirp(ptyTmpDir);
      await (0, _spawnAsync().default)('npm', ['init', '--yes'], {
        cwd: ptyTmpDir
      });
      await (0, _spawnAsync().default)('npm', ['install', 'node-pty-prebuilt'], {
        cwd: ptyTmpDir,
        stdio: ['pipe', 1, 2]
      });
      nodePty = require(`${ptyTmpDir}/node_modules/node-pty-prebuilt`);
    } catch (err) {
      log.info(`Run ${_chalk().default.cyan('npm -g install node-pty-prebuilt')} to install node pty`);
      throw new Error('Package node-pty-prebuilt is required to use PEPK tool');
    }
  }

  const ptySpawn = nodePty.spawn;

  const encryptToolPath = _path().default.join(_UserSettings().default.dotExpoHomeDirectory(), 'android_tools_pepk.jar');

  if (!_fsExtra().default.existsSync(encryptToolPath)) {
    log.info(`Downloading PEPK tool from Google Play to ${encryptToolPath}`);
    const downloadUrl = 'https://www.gstatic.com/play-apps-publisher-rapid/signing-tool/prod/pepk.jar';

    const file = _fsExtra().default.createWriteStream(encryptToolPath);

    const response = await (0, _axios().default)({
      url: downloadUrl,
      method: 'GET',
      responseType: 'stream'
    });
    const bar = new (_progress().default)('  downloading pepk tool [:bar] :rate/bps :percent :etas', {
      complete: '=',
      incomplete: ' ',
      width: 40,
      total: parseInt(response.headers['content-length'], 10)
    });
    response.data.pipe(file);
    response.data.on('data', chunk => bar.tick(chunk.length));
    await new Promise((resolve, reject) => {
      file.on('finish', resolve);
      file.on('error', reject);
    });
  }

  try {
    await new Promise((res, rej) => {
      const child = ptySpawn(javaExecutable, ['-jar', encryptToolPath, '--keystore', keystorePath, '--alias', keyAlias, '--output', outputPath, '--encryptionkey', encryptionKey], {
        name: 'pepk tool',
        cols: 80,
        rows: 30,
        cwd: process.cwd(),
        env: process.env
      });
      child.on('error', err => {
        log.error('error', err);
        rej(err);
      });
      child.on('exit', exitCode => {
        if (exitCode !== 0) {
          rej(exitCode);
        } else {
          res();
        }
      });
      child.write(keystorePassword + NEWLINE);
      child.write(keyPassword + NEWLINE);
    });
    log.info(`Exported and encrypted private App Signing Key to file ${outputPath}`);
  } catch (error) {
    throw new Error(`PEPK tool failed with return code ${error}`);
  } finally {
    _fsExtra().default.remove(ptyTmpDir);
  }
}

async function logKeystoreHashes(keystoreInfo, linePrefix = '') {
  const {
    keystorePath,
    keystorePassword,
    keyAlias
  } = keystoreInfo;
  const certFile = `${keystorePath}.cer`;

  try {
    await exportCertBinary(keystoreInfo, certFile);
    const data = await _fsExtra().default.readFile(certFile);

    const googleHash = _crypto().default.createHash('sha1').update(data).digest('hex').toUpperCase();

    const googleHash256 = _crypto().default.createHash('sha256').update(data).digest('hex').toUpperCase();

    const fbHash = _crypto().default.createHash('sha1').update(data).digest('base64');

    log.info(`${linePrefix}Google Certificate Fingerprint:     ${googleHash.replace(/(.{2}(?!$))/g, '$1:')}`);
    log.info(`${linePrefix}Google Certificate Hash (SHA-1):    ${googleHash}`);
    log.info(`${linePrefix}Google Certificate Hash (SHA-256):  ${googleHash256}`);
    log.info(`${linePrefix}Facebook Key Hash:                  ${fbHash}`);
  } catch (err) {
    if (err.code === 'ENOENT') {
      log.warn('Are you sure you have keytool installed?');
      log.info('keytool is a part of OpenJDK: https://openjdk.java.net/');
      log.info('Also make sure that keytool is in your PATH after installation.');
    }

    if (err.stdout) {
      log.info(err.stdout);
    }

    if (err.stderr) {
      log.error(err.stderr);
    }

    throw err;
  } finally {
    try {
      await _fsExtra().default.unlink(certFile);
    } catch (err) {
      if (err.code !== 'ENOENT') {
        log.error(err);
      }
    }
  }
}

function logKeystoreCredentials({
  keystorePassword,
  keyAlias,
  keyPassword
}, title = 'Keystore credentials', linePrefix = '') {
  log.info(`${linePrefix}${title}
${linePrefix}    Keystore password: ${_chalk().default.bold(keystorePassword)}
${linePrefix}    Key alias:         ${_chalk().default.bold(keyAlias)}
${linePrefix}    Key password:      ${_chalk().default.bold(keyPassword)}
  `);
}

async function createKeystore({
  keystorePath,
  keystorePassword,
  keyAlias,
  keyPassword
}, androidPackage) {
  try {
    return await (0, _spawnAsync().default)('keytool', ['-genkey', '-v', '-storetype', 'JKS', '-storepass', keystorePassword, '-keypass', keyPassword, '-keystore', keystorePath, '-alias', keyAlias, '-keyalg', 'RSA', '-keysize', '2048', '-validity', '10000', '-dname', `CN=${androidPackage},OU=,O=,L=,S=,C=US`]);
  } catch (error) {
    if (error.code === 'ENOENT') {
      log.warn('Are you sure you have keytool installed?');
      log.info('keytool is a part of OpenJDK: https://openjdk.java.net/');
      log.info('Also make sure that keytool is in your PATH after installation.');
    }

    throw error;
  }
}

async function generateUploadKeystore(uploadKeystorePath, androidPackage, experienceName) {
  const keystoreData = {
    keystorePassword: (0, _v().default)().replace(/-/g, ''),
    keyPassword: (0, _v().default)().replace(/-/g, ''),
    keyAlias: Buffer.from(experienceName).toString('base64'),
    keystorePath: uploadKeystorePath
  };
  await createKeystore(keystoreData, androidPackage);
  return keystoreData;
}
//# sourceMappingURL=../__sourcemaps__/credentials/AndroidCredentials.js.map