/*
	Licensed Material - Property of IBM

	(C) Copyright 2015, 2016 IBM Corp.

	Unless required by applicable law or agreed to in writing, software
	distributed under the License is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the License for the specific language governing permissions and
	limitations under the License.
*/


'use strict';

var moduleName = 'register-application';

//private modules
var errors = require('mdo-errors');
var messages = require('../externalizedStrings');
var strings = require('ibm-strings');
var mdoServerEndpoints = require('./constants/mdo-server-endpoints');
var defaultOptions = require('./constants/defaultOptions');

//3rd party modules
var log = require('npmlog');
var Q = require('q');
var FormData = require('form-data');
var http = require('http');
var Verror   = require('verror');

/*
* Parameters:
* options = {
*    protocol: <http-protocol>,    // Optional String. http || https. defaults to http
*    host: <host-dns-name>,        // Optional String. defaults to localhost
*    port: <host-port>,            // Optional Numeric. defaults to 10080
*    contextRoot: <host-context>,  // Optional String. Server root context.  defaults to 'worklightadmin'
*    userName: <user-id>,          // Optional String. Server login id. defaults to 'admin'
*    userPassword: <user-pwd>,     // Optional String. Server login id password.  defaults to 'admin'
*    runtime: <project-runtime>,   // Mandatory String. Project name (aka runtime, project context root)
*    timeout: <http-request-timeout>,// Optional Numeric (milliseconds).  http request timeout; defaults to 30000 (30 seconds)
*                                  // Overrideable by MFP_HTTP_DEFAULT_TIMEOUT env variable
*                                  // When timeout occurs, the request is aborted and an error is returned.
* }
*
* applicationKey =
*
*
 - iOS
 {
 "applicationKey": {
 "bundleId": "com.dummy",
 "version": "1.0",
 "clientPlatform": "ios"
 }
 }

 - Android
 {
 "applicationKey": {
 "packageName": "com.dummy",
 "version": "1.0",
 "clientPlatform": "android"
 }
 }

 - Windows (universal)
 {
 "applicationKey": {
 "assemblyName": "com.sampleone.bankApp",
 "version": "1.0",
 "clientPlatform":"windows"
 }
 }

 -Windows Phone 8:

 for older "windowsphone8" platform:

 {
 "applicationKey": {
 "assemblyName": "com.sampleone.bankApp",
 "version": "1.0",
 "clientPlatform":"windowsphone8"
 }
 }

* Returns:
* Q.deferred.promise.
*   On success - a string containing details about application register outcome
*   On failure - an Error object is returned
*/
var registerApplication = function(serverDetails, payload) {
  var d = Q.defer();

  // These default settings getting associated with the serverDetails Object are really here
  // to cover development environment scenario.  Not sure we should keep this logic?
  log.silly(moduleName, 'serverDetails: ' + (serverDetails ? JSON.stringify(serverDetails, null, ' ') : serverDetails));
  var timeout      = (serverDetails && serverDetails.timeout ? parseInt(serverDetails.timeout)*1000 : defaultOptions.TIMEOUT_MILLISECONDS);
  var protocol     = (serverDetails && serverDetails.protocol ? serverDetails.protocol : defaultOptions.PROTOCOL) + ':';  //jshint ignore:line
  var host         = (serverDetails && serverDetails.host ? serverDetails.host : defaultOptions.HOST);
  var port         = (serverDetails && serverDetails.port ? serverDetails.port : defaultOptions.PORT);
  var contextRoot  = (serverDetails && serverDetails.contextRoot ? serverDetails.contextRoot : defaultOptions.CONTEXT_ROOT);
  var userName     = (serverDetails && serverDetails.userName ? serverDetails.userName : defaultOptions.CREDENTIALS);
  var userPassword = (serverDetails && serverDetails.userPassword ? serverDetails.userPassword : defaultOptions.CREDENTIALS);
  var runtime      = (serverDetails && serverDetails.runtime ? serverDetails.runtime : 'mfp');
  log.silly(moduleName, 'serverDetails after defaults applied: ' + (serverDetails ? JSON.stringify(serverDetails, null, ' ') : serverDetails));

  log.silly(moduleName, 'register payload: ' + (payload ? JSON.stringify(payload, null, ' ') : payload));

  // convert the serverDetails into s json Object
  //var payloadObject = (serverDetails && serverDetails.json ? serverDetails.json : null);
  var payloadObject = (payload ? payload : null);

  var appInfoForError = _generateAppInfoErrorString(payloadObject);

  // Set trace level
  log.level = global.MDO_CLI_LOG_LEVEL ? global.MDO_CLI_LOG_LEVEL : log.level;
  var path = strings.format(mdoServerEndpoints.REGISTER_APPLICATION, contextRoot, runtime);
  var postRawBody = require('../rest-client/rest-client.js').postRawBody;
  var requestPromise = postRawBody(host, port, path, protocol, userName, userPassword, timeout, payloadObject);
  requestPromise.then (function () {
    d.resolve({
      appInfo: strings.format(messages.registeredApp, payload.applicationKey.clientPlatform)
    });
  }, function (err) {
    log.verbose(moduleName, 'request error:' + err);
    var formerr = new Verror(err, 'failed application deploy');
    formerr.name = 'DeployAppError';
    formerr.appInfo = appInfoForError;
    d.reject(formerr);
  });

  return d.promise;
}

var _generateAppInfoErrorString = function (jsonObj) {
  var dotIDName;
  var platform = jsonObj.applicationKey.clientPlatform;
  if(platform === 'android') {
      dotIDName = 'packageName';
  } else if (platform === 'ios') {
      dotIDName = 'bundleId';
  } else {
      dotIDName = 'assemblyName';
  }
  return strings.format(messages.registeredAppFailed, platform);
}

module.exports = {
  registerApplication: registerApplication
};
