// Generated by CoffeeScript 2.3.1
// ========================================
// The Haruka class
var Discord, Haruka, fs;

fs = require('fs');

Discord = require('discord.js');

/**
 * The options object Haruka should be instantiated with.
 * @typedef {Object} HarukaOptions
 * @property {Object} config - The configuration file.
    See `example-config.json`
 * @property {String} version - Haruka’s version.
    Defaults to `options.config.version`
 * @property {String} prefix - Haruka’s command prefix, such as `-h`.
    This must be defined.
 * @property {HarukaDefault} default - Haruka’s catch-all function.
    If Haruka detects that her prefix was sent but no function was called,
    this function can warn the sender.
 */
/**
 * A catchall function, called when a message starts with Haruka's prefix,
 * but no function matched its regular expression.
 * @callback HarukaDefault
 * @param {Message} msg - A DiscordJS Discord message.
 */
/**
 * Describes a Haruka function. These functions are passed to
 * the Haruka instance via Haruka::add()
 * @typedef {Object} HarukaFn
 * @property {String} name - The function name.
 * @property {HarukaHandler} handler - The Haruka message handler
 * @property {RegExp} [regex] - The regular expression that should trigger
 * this function. If this function is a special function, omit this property.
 * @property {Object} help - This function's help descriptions.
 * @property {String} [help.short] - This function's short help description.
 * Can be omitted if help.hidden is set to true.
 * @property {String} help.long - This function's long help description.
 * @property {Boolean} [help.hidden=true] - Whether this function should show up
 * in the generic help list. Defaults to true.
 */
/**
 * A Haruka message handler.
 * @callback HarukaHandler
 * @param {Message} msg - A DiscordJS Discord message
 * @param {Array} [match] - The RegExp match that triggered this message.
    This argument is omitted if this function is a Special function.
 * @param {Haruka} H - The Haruka instance this function is attached to.
 */
/**
 * The Haruka class.
 * @author MindfulMinun
 * @param {HarukaOptions} options - Haruka’s options.
 * @since 2.0.0
 * @version 2.0.0
 */
Haruka = class Haruka {
  constructor(options) {
    var ref, ref1, ref2;
    // Set a couple variables for later
    this.client = new Discord.Client;
    this.config = (ref = options.config) != null ? ref : {};
    this.version = (ref1 = options.version) != null ? ref1 : this.config.version;
    this.default = options.default;
    /**
     * Haruka's function prefix, such as `-h`.
     * It musn't contain any whitespace.
     * @type {String}
     */
    this.prefix = (function() {
      var ref3;
      if ((ref2 = (ref3 = options.prefix) != null ? ref3 : this.config.prefix) != null) {
        return ref2;
      } else {
        throw Error("Haruka requires a command prefix.");
      }
    }).call(this);
    if (/\s/.test(this.prefix)) {
      throw Error("Haruka’s prefix should not contain any whitespace.");
    }
    /**
     * A collection of functions, meant to be added via
     * `Haruka::add('function', fn)`
     * @type {Array<HarukaFn>}
     */
    this.functions = [];
    /**
     * A collection of special functions, meant to be
     * added via `Haruka::add('special', fn)`
     * @type {Array<HarukaFn>}
     */
    this.specials = [];
  }

  /**
   * Haruka will attempt to reply to the given Discord message
   * if it starts with the prefix. If it can't find one,
   * it will call the `default` function passed during instantiation.
   * @author MindfulMinun
   * @param {Message} msg - The discord.js Discord message
   * @returns {*} The return value of the handler function or
  `undefined` if the message was sent by a bot or doesn't
  start with the prefix.
   * @since 0.1.0
   * @version 2.0.0
   */
  try(msg) {
    var commands, fn, i, j, len, len1, ref, ref1, regexMatch, temp;
    ref = this.specials;
    // ========================================
    // Run Specials first
    for (i = 0, len = ref.length; i < len; i++) {
      fn = ref[i];
      // Break if handler returns a truthy value.
      if (temp = fn.handler(msg, this)) {
        return temp;
      }
    }
    // ========================================
    // Functions

    // Check if the message starts with the prefix,
    // and it's not from another bot.
    if ((!msg.content.startsWith(this.prefix)) || msg.author.bot) {
      return;
    }
    commands = msg.content.replace(this.prefix, '').trim();
    ref1 = this.functions;
    // Run through all the commands and see if one matches.
    for (j = 0, len1 = ref1.length; j < len1; j++) {
      fn = ref1[j];
      regexMatch = fn.regex.exec(commands);
      if (regexMatch) {
        return fn.handler(msg, regexMatch, this);
      }
    }
    // Catchall
    return this.default(msg);
  }

  /**
   * Adds a function to Haruka. This function will be called if a
   * message's content matches its RegExp
   * @author MindfulMinun
   * @param {String} type - An enumerated string, either
  "function" or "special"
   * @param {HarukaFn} fn - A Haruka message handler function.
   * @returns {Haruka} The Haruka object with the function added to it.
   * @since Sep 23, 2018 - 2.0.0
   * @version 2.0.0
   */
  add(type, fn) {
    switch (type) {
      case "function":
        this.functions.push(fn);
        break;
      case "special":
        this.specials.push(fn);
        break;
      default:
        throw Error(`Expected type to be either “function” or “special”, was instead “${type}”`);
    }
    return this;
  }

};

module.exports = Haruka;