/*******************************************

*                                         *
* This util was created by Marius Olbertz *
* Please thank Marius on GitHub /owlbertz *
* or the web http://www.mariusolbertz.de/ *
*                                         *
******************************************/

‘use strict’;

!function($) {

const keyCodes = {

9: 'TAB',
13: 'ENTER',
27: 'ESCAPE',
32: 'SPACE',
37: 'ARROW_LEFT',
38: 'ARROW_UP',
39: 'ARROW_RIGHT',
40: 'ARROW_DOWN'

}

var commands = {}

var Keyboard = {

keys: getKeyCodes(keyCodes),

/**
 * Parses the (keyboard) event and returns a String that represents its key
 * Can be used like Foundation.parseKey(event) === Foundation.keys.SPACE
 * @param {Event} event - the event generated by the event handler
 * @return String key - String that represents the key pressed
 */
parseKey(event) {
  var key = keyCodes[event.which || event.keyCode] || String.fromCharCode(event.which).toUpperCase();

  // Remove un-printable characters, e.g. for `fromCharCode` calls for CTRL only events
  key = key.replace(/\W+/, '');

  if (event.shiftKey) key = `SHIFT_${key}`;
  if (event.ctrlKey) key = `CTRL_${key}`;
  if (event.altKey) key = `ALT_${key}`;

  // Remove trailing underscore, in case only modifiers were used (e.g. only `CTRL_ALT`)
  key = key.replace(/_$/, '');

  return key;
},

/**
 * Handles the given (keyboard) event
 * @param {Event} event - the event generated by the event handler
 * @param {String} component - Foundation component's name, e.g. Slider or Reveal
 * @param {Objects} functions - collection of functions that are to be executed
 */
handleKey(event, component, functions) {
  var commandList = commands[component],
    keyCode = this.parseKey(event),
    cmds,
    command,
    fn;

  if (!commandList) return console.warn('Component not defined!');

  if (typeof commandList.ltr === 'undefined') { // this component does not differentiate between ltr and rtl
      cmds = commandList; // use plain list
  } else { // merge ltr and rtl: if document is rtl, rtl overwrites ltr and vice versa
      if (Foundation.rtl()) cmds = $.extend({}, commandList.ltr, commandList.rtl);

      else cmds = $.extend({}, commandList.rtl, commandList.ltr);
  }
  command = cmds[keyCode];

  fn = functions[command];
  if (fn && typeof fn === 'function') { // execute function  if exists
    var returnValue = fn.apply();
    if (functions.handled || typeof functions.handled === 'function') { // execute function when event was handled
        functions.handled(returnValue);
    }
  } else {
    if (functions.unhandled || typeof functions.unhandled === 'function') { // execute function when event was not handled
        functions.unhandled();
    }
  }
},

/**
 * Finds all focusable elements within the given `$element`
 * @param {jQuery} $element - jQuery object to search within
 * @return {jQuery} $focusable - all focusable elements within `$element`
 */
findFocusable($element) {
  if(!$element) {return false; }
  return $element.find('a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, *[tabindex], *[contenteditable]').filter(function() {
    if (!$(this).is(':visible') || $(this).attr('tabindex') < 0) { return false; } //only have visible elements and those that have a tabindex greater or equal 0
    return true;
  });
},

/**
 * Returns the component name name
 * @param {Object} component - Foundation component, e.g. Slider or Reveal
 * @return String componentName
 */

register(componentName, cmds) {
  commands[componentName] = cmds;
},  

/**
 * Traps the focus in the given element.
 * @param  {jQuery} $element  jQuery object to trap the foucs into.
 */
trapFocus($element) {
  var $focusable = Foundation.Keyboard.findFocusable($element),
      $firstFocusable = $focusable.eq(0),
      $lastFocusable = $focusable.eq(-1);

  $element.on('keydown.zf.trapfocus', function(event) {
    if (event.target === $lastFocusable[0] && Foundation.Keyboard.parseKey(event) === 'TAB') {
      event.preventDefault();
      $firstFocusable.focus();
    }
    else if (event.target === $firstFocusable[0] && Foundation.Keyboard.parseKey(event) === 'SHIFT_TAB') {
      event.preventDefault();
      $lastFocusable.focus();
    }
  });
},
/**
 * Releases the trapped focus from the given element.
 * @param  {jQuery} $element  jQuery object to release the focus for.
 */
releaseFocus($element) {
  $element.off('keydown.zf.trapfocus');
}

}

/*

* Constants for easier comparing.
* Can be used like Foundation.parseKey(event) === Foundation.keys.SPACE
*/

function getKeyCodes(kcs) {

var k = {};
for (var kc in kcs) k[kcs[kc]] = kcs[kc];
return k;

}

Foundation.Keyboard = Keyboard;

}(jQuery);