'use strict';

var _stringify = require('babel-runtime/core-js/json/stringify');

var _stringify2 = _interopRequireDefault(_stringify);

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

var Command = require('ronin').Command;
var spawn = require('child_process').spawn;
var fs = require('fs');
var temp = require('temp');
var async = require('async');
var debug = require('debug');
var log = debug('cli:config');
log.error = debug('cli:config:error');
var utils = require('../../utils');

module.exports = Command.extend({
  desc: 'Opens the config file for editing in $EDITOR',

  run: function run(name) {
    utils.getIPFS(function (err, ipfs) {
      if (err) {
        throw err;
      }
      var editor = process.env.EDITOR;

      if (!editor) {
        throw new Error('ENV variable $EDITOR not set');
      }

      function getConfig(next) {
        ipfs.config.show(function (err, config) {
          if (err) {
            log.error(err);
            next(new Error('failed to get the config'));
          }

          next(null, config);
        });
      }

      function saveTempConfig(config, next) {
        temp.open('ipfs-config', function (err, info) {
          if (err) {
            log.error(err);
            next(new Error('failed to open the config'));
          }

          fs.write(info.fd, (0, _stringify2.default)(config, null, 2));
          fs.close(info.fd, function (err) {
            if (err) {
              log.error(err);
              next(new Error('failed to open the config'));
            }
          });

          next(null, info.path);
        });
      }

      function openEditor(path, next) {
        var child = spawn(editor, [path], {
          stdio: 'inherit'
        });

        child.on('exit', function (err, code) {
          if (err) {
            log.error(err);
            throw new Error('error on the editor');
          }

          next(null, path);
        });
      }

      function readTempConfig(path, next) {
        fs.readFile(path, 'utf8', function (err, data) {
          if (err) {
            log.error(err);
            next(new Error('failed to get the updated config'));
          }

          try {
            next(null, JSON.parse(data));
          } catch (err) {
            log.error(err);
            next(new Error('failed to parse the updated config "' + err.message + '"'));
          }
        });
      }

      function saveConfig(config, next) {
        config = utils.isDaemonOn() ? new Buffer((0, _stringify2.default)(config)) : config;

        ipfs.config.replace(config, function (err) {
          if (err) {
            log.error(err);
            next(new Error('failed to save the config'));
          }

          next();
        });
      }

      async.waterfall([getConfig, saveTempConfig, openEditor, readTempConfig, saveConfig], function (err) {
        if (err) {
          throw err;
        }
      });
    });
  }
});