// Copyright IBM Corp. 2016. All Rights Reserved.
// Node module: apiconnect-cli-apps
// US Government Users Restricted Rights - Use, duplication or disclosure
// restricted by GSA ADP Schedule Contract with IBM Corp.

var Promise = require('bluebird');
var _ = require('lodash');
var cliUtil = require('apiconnect-cli-util');
var collectiveApi = require('apiconnect-collective-controller-api');
var crypto = require('crypto');
var logger = require('apiconnect-cli-logger');
var os = require('os');
var path = require('path');
var rimraf = Promise.promisify(require('rimraf'));
var f = require('util').format;
var fs = Promise.promisifyAll(require('fs'));
var fsExtra = Promise.promisifyAll(require('fs-extra'));
var mkdirp = Promise.promisify(require('mkdirp'));

var build = require('../build/build');

var deploy = Promise.promisify(collectiveApi.fileService.deploy);
var listIhsInfo = Promise.promisify(collectiveApi.listIhsInfo);
var getHosts = Promise.promisify(collectiveApi.server.getHosts);

function libertyPublish(server, providerOrg, providerApp, projectDir, projectType) {
  var ts = +new Date();
  var tmpPath = path.join(os.tmpdir(), Math.random() + '-' + ts);
  var clusterName = f('%s-%s-%d', providerApp.name, providerApp.id, ts);
  var vHostHeader = f('%s.%s', clusterName, providerOrg.name);

  var tarFilePath = path.join(tmpPath, clusterName + '-package.tgz');
  var tmpProjectDir = path.join(tmpPath, 'project');

  var keystorePassword = new Buffer(crypto.randomBytes(20));
  keystorePassword = keystorePassword.toString('base64');

  return mkdirp(tmpProjectDir).then(function() {
    logger.writeln('...preparing project');
    return fsExtra.copyAsync(projectDir, tmpProjectDir);
  }).then(function() {
    var pkgJson = require(path.resolve(projectDir, 'package.json'));
    var isGateway = pkgJson.APIConnectGateway;
    if (isGateway) {
      return;
    }
    return prepareProject(tmpProjectDir, vHostHeader);
  }).then(function() {
    logger.writeln('...building package for deploy');
    return build(tmpProjectDir, { zip: false, outputFilePath: tarFilePath });
  }).then(function() {
    return lookupLibertyDetails(server, providerOrg, providerApp);
  }).then(function(creds) {
    var l = creds.liberty;
    l.vHostHeader = vHostHeader;
    return listIhsInfo({
      host: l.controllerHosts[0].host,
      port: l.controllerHosts[0].port,
      user: l.username,
      password: l.password,
      autoAcceptCertificates: true,
    }).then(function(ihsInfo) {
      return {
        liberty: l,
        ihsInfo: _.map(ihsInfo, function(p, h) { return h + ':' + p; }),
      };
    }).catch(function(err) {
      logger.debug('Unable to retrieve IHS info.');
      logger.debug(err);
      return {
        liberty: l,
        ihsInfo: [ 'IHS endpoint information is not available' ],
      };
    });
  }).then(function(creds) {
    var l = creds.liberty;
    return getHosts({
      host: l.controllerHosts[0].host,
      port: l.controllerHosts[0].port,
      user: l.username,
      password: l.password,
      autoAcceptCertificates: true,
    }).then(function(hosts) {
      creds.liberty.registeredHosts = hosts;
      return creds;
    });
  }).then(function(creds) {
    var scale = creds.liberty.registeredHosts.ids.length;
    logger.writeln(
      '...uploading packages to %s:%s, scale: %d',
      creds.liberty.controllerHosts[0].host, creds.liberty.controllerHosts[0].port, scale
    );

    var deployOptions = {
      srcFile: tarFilePath,
      host: creds.liberty.controllerHosts[0].host,
      port: creds.liberty.controllerHosts[0].port,
      username: creds.liberty.username,
      password: creds.liberty.password,
      serverName: clusterName,
      clusterName: clusterName,
      keystorePassword: keystorePassword,
      instances: scale,
    };
    return deploy(deployOptions).then(function() {
      return rimraf(tmpPath, { glob: false }).catch(function(err) {
        logger.debug('Unable to remove tmpdir %s: %s', tmpPath, err.message);
      });
    }).then(function() {
      return creds;
    });
  });
}
module.exports = libertyPublish;

function prepareProject(projectDir, vHostHeader) {
  return fs.writeFileAsync(
    path.join(projectDir, 'server.json'),
    JSON.stringify({
      vHost: vHostHeader,
    }),
    'utf8'
  );
}

function lookupLibertyDetails(server, providerOrg, providerApp) {
  return cliUtil.ProviderApps.get({
    server: server,
    org: providerOrg.id,
    app: providerApp.id,
    getEncrypted: true,
  });
}
