/*
	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 Q = require('q');
var inquirer = require('inquirer');
var nopt = require('nopt');
var fs = require('fs');
var path = require('path');

var externalizedStrings = require('./externalizedStrings');
var errors = require('mdo-errors');
var strings = require('ibm-strings');
var exec = require('mdo-exec').run;

//var ADAPTER_FOLDER = 'adapters';

var promptParameters = function () {
  var deferred = Q.defer();

  var prompts = [
    {
      name: 'adapterName',
      message: externalizedStrings.enterName,
      validate: function(input) {
        var err = validateAdapterName(input);
        if (err === null) {
          return true;
        }
        else {
          console.log();
          strings.fatal(err.description);
          return false;
        }
      }
    },
    {
      name: 'adapterType',
      type: 'list',
      choices: [
        {
          name: externalizedStrings.HTTPAdapterType,
          value: 'http'
        },
        {
          name: externalizedStrings.SQLAdapterType,
          value: 'sql'
        },
        {
          name: externalizedStrings.JAVAAdapterType,
          value: 'java'
        }
/*        {
          name: externalizedStrings.JMSAdapterType,
          value: 'jms'
        },
        {
          name: externalizedStrings.SAPAdapterType,
          value: 'sap'
        }
*/
      ],
      message: externalizedStrings.selectAdapterType
    },
    {
      name: 'package',
      message: externalizedStrings.enterPackage,
      validate: function(input) {
        var err = validatePackageName(input, 'java');
        if (err === null) {
          return true;
        }
        else {
          console.log();
          strings.fatal(err.description);
          return false;
        }
      },
      when: function(response) {
        return response.adapterType === 'java';
      }
    },
    {
      name: 'groupID',
      message: externalizedStrings.enterGroupID,
      validate: function(input) {
        var err = validateGroupID(input);
        if (err === null) {
          return true;
        }
        else {
          console.log();
          strings.fatal(err.description);
          return false;
        }
      }
    }
  ];

  inquirer.prompt(prompts, function (answers) {
    deferred.resolve(answers);
  });

  return deferred.promise;
};

var createAdapter = function(name, adapterType, packageName, groupID) {
  var deferred = Q.defer();

  // For now make adapters in cwd
  //if (!fs.existsSync(ADAPTER_FOLDER)){
  //  fs.mkdirSync(ADAPTER_FOLDER);
  //}
  //
  //process.chdir(ADAPTER_FOLDER);

  var mavenParams = [
    'archetype:generate', '-B',
    '-DarchetypeGroupId=com.ibm.mfp',
    '-DarchetypeArtifactId=adapter-maven-archetype-' + adapterType,
    '-DgroupId=' + groupID,
    '-Dversion=1.0-SNAPSHOT',
    '-DartifactId=' + name
  ];
  if (adapterType === 'java') mavenParams.push('-Dpackage=' + packageName);

  console.log(strings.format(externalizedStrings.creatingAdapter, adapterType, name));

  // exec echo to pipe newline in mavenParams to mvn, this is because the mvn command requires an interactive confirmation prompt
  exec('mvn', mavenParams).then(function() {
    deferred.resolve();
  }, function(err) {
    deferred.reject(err);
  });

  return deferred.promise;
};

/**
 * actually do the work of the command
 */
module.exports.run = function(argv) {
  var deferred = Q.defer();

  var opts = nopt({
    type: String,
    package: String,
    group: String
  }, {
    t: '--type',
    p: '--package',
    g: '--group'
  }, argv, 0);

  // No arguments -> interactive mode
  var name;
  if(!opts.type && !opts.package && !opts.group && opts.argv.remain.length === 0) {
    promptParameters().then(function(input) {
      name = input.adapterName;
      return createAdapter(name, input.adapterType, input.package, input.groupID).then(function () {
        console.log(strings.format(externalizedStrings.successfulCreate, name));
        deferred.resolve();
      }, function (err) {
        console.log(externalizedStrings.errorCreate);
        console.log(err.stdOut);
        var errorCreate = errors.getError('ADAPTERCREATEERROR');
        strings.fatal(errorCreate.description);
        deferred.reject(err);
      });
    });
  } else {  // direct mode
    name = opts.argv.remain[0];
    validateParams(name, opts.type, opts.package, opts.group, opts.argv.remain).then(function() {
      return createAdapter(name, opts.type, opts.package, opts.group).then(function() {
        console.log(strings.format(externalizedStrings.successfulCreate, name));
        deferred.resolve();
      }, function(err) {
        console.log(externalizedStrings.errorCreate);
        console.log(err.stdOut);
        var errorCreate = errors.getError('ADAPTERCREATEERROR');
        strings.fatal(errorCreate.description);
        deferred.reject(errorCreate);
      });
    }, function(err) {
      strings.fatal(err.description);
      deferred.reject(err);
    });
  }

  return deferred.promise;
};

function validateParams (name, adapterType, packageName, groupID, remain) {
  var deferred = Q.defer();

  var validationList = [
    validateAdapterName(name),
    validateAdapterType(adapterType),
    validatePackageName(packageName, adapterType),
    validateGroupID(groupID)
  ];

  var noError = true;

  validationList.forEach(function(error) {
    if (error) {
      noError = false;
      strings.fatal(error.description);
    }
  });

  if (noError) {
    if (remain.length > 1) deferred.reject(errors.getError('INVALIDADAPTERPARAMS'));
    else deferred.resolve();
  }
  else {
    deferred.reject(errors.getError('ADAPTERCREATEERROR'));
  }

  return deferred.promise;
}

function validateAdapterName (name) {
  var error = null;

  if (typeof name === 'undefined' || name === null || name.trim().length === 0) {
    error = errors.getError('MISSINGNAME');
  }
  else if (!name.match(/^[a-zA-Z_]+/) || !name.match(/(^[a-zA-Z0-9_\-\.]+$)/) || !name.match(/([a-zA-Z0-9_\-]+$)/) ) {
    error = errors.getError('INVALIDNAME');
  }
  else if (fs.existsSync(name)) {
    error = errors.getError('FILEEXISTS');
  }

  return error;
}

function validateAdapterType (type) {
  var error = null;

  var validTypes = [
    'http',
    'sql',
    'java'
//    'jms',
//    'sap'
  ];

  if (typeof type === 'undefined' || type === null || type.trim().length === 0) {
    error = errors.getError('MISSINGADAPTERTYPE');
  }
  else if (validTypes.indexOf(type) === -1) {
    error = errors.getError('INVALIDADAPTERTYPE');
  }

  return error;
}

function validatePackageName (name, adapterType) {
  var error = null;

  if (adapterType === 'java') {
    if (typeof name === 'undefined' || name === null || name.trim().length === 0) {
      error = errors.getError('MISSINGPACKAGENAME');
    }
    else if (!name.match(/^[a-zA-Z_]([a-zA-Z0-9_])*([\.][a-zA-Z_]([a-zA-Z0-9_])*)*$/)) {
      if (!name.match(/^(?!^\.)(?!.*[-_.]$)/))
        error = errors.getError('INVALIDPACKAGEPERIOD');
      else
        error = errors.getError('INVALIDNAME');
    }
  }
  else if (name) {
    error = errors.getError('CANNOTADDPACKAGENAME');
  }

  return error;
}

function validateGroupID (id) {
  var error = null;

  if (typeof id === 'undefined' || id === null || id.trim().length === 0) {
    error = errors.getError('MISSINGGROUPID');
  }
  else if (!id.match(/^[a-zA-Z_]([a-zA-Z0-9_])*([\.][a-zA-Z_]([a-zA-Z0-9_])*)*$/)) {
    if (!id.match(/^(?!^\.)(?!.*[-_.]$)/))
      error = errors.getError('INVALIDGROUPPERIOD');
    else
      error = errors.getError('INVALIDID');
  }

  return error;
}

// return the path to the md file (relative to basePath) for the specific command
module.exports.getHelpFilePath = function(basePath) {
  return path.join(basePath, 'mdo-adapter-actions', 'doc', 'create.txt');
};

module.exports.validateAdapterName = validateAdapterName;
module.exports.validateAdapterType = validateAdapterType;
module.exports.validatePackageName = validatePackageName;
module.exports.validateGroupID = validateGroupID;
