/*
	Licensed Material - Property of IBM

	(C) Copyright 2015 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 fs = require('fs');
var strings = require('ibm-strings');
var path = require('path');
var inquirer = require('inquirer');
var defaultKeys = require("./global_keys.json");
var errors = require('mdo-errors');
var log = require('npmlog');
var messages = strings({
  locales: path.resolve(__dirname, '..', 'nls')
});
var config_api = require('./config_api.js');
var EXIT_INTERACTIVE = "finished_exit";
var DEV_BROWSER = "development_browser";
//the path to the config_cli.json file

/*
 * Ran if user inputed mdo config <key>
 * Shows the interactive menu to change the value for the inputted key
 */
var withKey = function(key) {
  var d = Q.defer();
  if (defaultKeys[key]) {
    config_api.getValueForKey(key).then(function(val) {
      console.log(val);
      d.resolve();
    });
  } else {
    strings.fatal(errors.getError('INVALIDCONFIGKEY', key).description);
    d.reject(errors.getError('INVALIDCONFIGKEY', key));
  }
  return d.promise;
};
/*
 * Ran if user inputted mdo config <key> <value>
 * Updates the value for the key
 */
function withKeyAndValue(key, val) {
  var d = Q.defer();
  //checks if the key exists and not the finished_exit key
  if (defaultKeys[key] && key !== EXIT_INTERACTIVE) {
    //checks if they chose to put in the location for the new web browser
    if (key === DEV_BROWSER && val === messages.newBrowserLabel) {
      inquirer.prompt([{
        type: 'input',
        name: 'location',
        message: messages.locationLabel,
        validate: function(input) {
          var result = validatePath(key, input);
          if (result) {
            return true;
          } else {
            d.reject(errors.getError('ILLEGALPATH'));
            return errors.getError('ILLEGALPATH').description;
          }
        }
      }], function(answer) {
        var filepath = answer.location.replace(/\\/g, '/');
        updateGlobalConfig(key, filepath).then(
          function() {
            d.resolve();
          },
          function(err) {
            d.reject(err);
          });
      });
    } else {
      //checks if the selected key has choices
      if (defaultKeys[key].hasOwnProperty('choices')) {
        // if it does have choices make sure the inputted value is a valid choice
        var foundVal = false;
        var c = defaultKeys[key].choices;
        for (var i = 0; i < c.length; i++) {
          if (c[i].value === val) foundVal = true;
        }
        if (foundVal || key === DEV_BROWSER && validatePath(key, val)) {
          updateGlobalConfig(key, val).then(
            function() {
              d.resolve();
            },
            function(err) {
              d.reject(err);
            });
        } else {
          strings.fatal(errors.getError('INVALIDCONFIGVALUE', val, key).description);
          d.reject(errors.getError('INVALIDCONFIGVALUE', val, key));
        }
      } else {
        //if the key doesn't have choices
        //then it just sets the new value for the key
        updateGlobalConfig(key, val).then(
          function() {
            d.resolve();
          },
          function(err) {
            d.reject(err);
          });
      }
    }
  } else {
    strings.fatal(errors.getError('INVALIDCONFIGKEY', key).description);
    d.reject(errors.getError('INVALIDCONFIGKEY', key));
  }

  return d.promise;
}

/*
 * Ran if user inputed mdo config
 * Shows the list of global keys
 */
var interactiveMode = function() {
  var d = Q.defer();
  var choices = [];
  //turns the keys into user frinedly named options
  var k = 0;
  for (var key in defaultKeys) {
    if (k === 0 || k === 1) choices.push(new inquirer.Separator('----------------------------------'));
    choices.push(defaultKeys[key]);
    k++;
  }
  inquirer.prompt([{
    type: 'list',
    name: 'key',
    message: messages.selectSetting,
    choices: choices
  }], function(answer) {
    if (answer.key !== EXIT_INTERACTIVE) {
      var key = answer.key;

      if (defaultKeys[key]) {
        config_api.getValueForKey(key).then(function(val) {
          strings.info(strings.format(messages.currentValue, key, val) + '\n');
          inquirer.prompt([{
            type: defaultKeys[key].type,
            name: 'value',
            message: messages.enterNewValue,
            choices: defaultKeys[key].choices,
            default: defaultKeys[key].value ? defaultKeys[key].value : '',
            validate: function(input) {
              var result = validateInput(key, input);
              if (result) {
                strings.fatal(result.description + '\n');
                return false;
              }
              return true;
            }
          }], function(answer) {
            
            withKeyAndValue(key, answer.value).then(function() {
              //Loop back to main list of global keys
              interactiveMode();
            });
          });
        });
      } else {
        strings.fatal(errors.getError('INVALIDCONFIGKEY', String(key)).description);
        d.reject(errors.getError('INVALIDCONFIGKEY', key));
      }
    } else {
      //user chose the finish exit config choice
      d.resolve();
    }
  });
  return d.promise;
};

/*
 * Updates the config_cli.json file with the new value for the selected key
 */
function updateGlobalConfig(key, val) {
  var d = Q.defer();
  log.verbose(messages.updateConfig, strings.format(messages.updatingConfigValue, key, val));
  config_api.setValueForKey(key, val).then(
    function() {
      log.verbose(messages.updateConfig, messages.updatedConfig);
      d.resolve();
    },
    function(err) {
      d.reject(err);
    }
  );
  return d.promise;
}

function validateInput(key, input) {
  var inputType = defaultKeys[key].inputType;
  if (inputType === 'prefix' && !input.match(/^[a-zA-Z]([a-zA-Z0-9])*([\.][a-zA-Z0-9]([a-zA-Z0-9])*)*$/)) {
    return errors.getError('INVALIDVALUEFORMAT').description;
  } else if (inputType === 'timeout' && isNaN(input)) {
    return errors.getError('INVALIDTIMEOUT');
  }
  return null;
}

function validatePath(key, filepath) {
  var pathType = defaultKeys[key].pathType;
  try {
    fs.statSync(filepath);
    if (process.platform !== 'darwin' && ((fs.lstatSync(path.normalize(filepath)).isDirectory() && pathType === 'file') || (fs.lstatSync(path.normalize(filepath)).isFile() && pathType === 'directory'))) {
      return false;
    }
    return true;
  } catch (err) {
    return false;
  }
}

module.exports = {
  interactiveMode: interactiveMode,
  withKey: withKey,
  withKeyAndValue: withKeyAndValue
};
