'use strict';

var EventEmitter = require('events').EventEmitter;
var mixin = require('merge-descriptors');

function Command(data, token) {
  this.data = data;
  this.token = token;
  this.actions = [];
  this.helpEntries = [];

  mixin(this, EventEmitter.prototype, false);
}

Command.prototype._checkToken = function() {
  if(!this.token) {
    console.warn('Without a validation token anyone can execute your command.');
  } else {
    if(this.data.token !== this.token) throw 'Invalid token';
  }
}

Command.prototype._findAction = function (text) {
  var action;

  for(var i = 0; i < this.actions.length; i++) {
    action = this.actions[i];
    if(action.pattern.test(text)) {
      return action;
    }
  }
};

Command.prototype.action = function (pattern, help, callback) {
  if(typeof pattern !== RegExp) pattern = new RegExp(pattern);
  this.actions.push({pattern: pattern, callback: callback});
  this.helpEntries.push(help);
};

Command.prototype._getHelpText = function () {
  var command = this.data.command;
  var entries = this.helpEntries.map(function (entry) {
    return '• ' + command + ' ' + entry;
  });

  return {
    response_type: 'ephemeral',
    text: entries.join('\n')
  };
}

Command.prototype._finish = function (response) {
  this.emit('success', response);
}

Command.prototype.execute = function () {
  var data = this.data;

  try {
    this._checkToken();

    var text = data.text.trim();
    var action = this._findAction(text);

    if(text === 'help') {
      this.emit('success', this._getHelpText());
    } else if(action) {
      action.callback(data, action.pattern.exec(text), this._finish.bind(this));
    } else {
      this.emit('error', 'No matching action found to handle ' + text);
    }
  } catch(e) {
    this.emit('error', e);
  }
};

exports.Command = Command;
@@ -63,49 +63,207 @@
 er;%0A
-var mixin = require('merge-descriptors');
+%0Afunction mixin(receiver, supplier) %7B%0A  Object.keys(supplier).forEach(function (property) %7B%0A    Object.defineProperty(receiver, property, Object.getOwnPropertyDescriptor(supplier, property));%0A  %7D);%0A%7D
 %0A%0Afu
@@ -381,16 +381,16 @@
  = %5B%5D;%0A%0A
+
   mixin(
@@ -421,15 +421,8 @@
 type
-, false
 );%0A%7D

Remove dependency on merge-descriptors