import { HAS_PASSIVE_EVENT_SUPPORT } from '../constants/env';
import { ROOT_EVENT_NAME_PREFIX, ROOT_EVENT_NAME_SEPARATOR } from '../constants/events';
import { RX_BV_PREFIX } from '../constants/regex';
import { isObject } from './inspect';
import { kebabCase } from './string';

// --- Utils ---

// Normalize event options based on support of passive option
// Exported only for testing purposes
export var parseEventOptions = function parseEventOptions(options) {
  /* istanbul ignore else: can't test in JSDOM, as it supports passive */
  if (HAS_PASSIVE_EVENT_SUPPORT) {
    return isObject(options) ? options : {
      capture: !!options || false
    };
  } else {
    // Need to translate to actual Boolean value
    return !!(isObject(options) ? options.capture : options);
  }
};

// Attach an event listener to an element
export var eventOn = function eventOn(el, eventName, handler, options) {
  if (el && el.addEventListener) {
    el.addEventListener(eventName, handler, parseEventOptions(options));
  }
};

// Remove an event listener from an element
export var eventOff = function eventOff(el, eventName, handler, options) {
  if (el && el.removeEventListener) {
    el.removeEventListener(eventName, handler, parseEventOptions(options));
  }
};

// Utility method to add/remove a event listener based on first argument (boolean)
// It passes all other arguments to the `eventOn()` or `eventOff` method
export var eventOnOff = function eventOnOff(on) {
  var method = on ? eventOn : eventOff;
  for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
    args[_key - 1] = arguments[_key];
  }
  method.apply(void 0, args);
};

// Utility method to prevent the default event handling and propagation
export var stopEvent = function stopEvent(event) {
  var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
    _ref$preventDefault = _ref.preventDefault,
    preventDefault = _ref$preventDefault === void 0 ? true : _ref$preventDefault,
    _ref$propagation = _ref.propagation,
    propagation = _ref$propagation === void 0 ? true : _ref$propagation,
    _ref$immediatePropaga = _ref.immediatePropagation,
    immediatePropagation = _ref$immediatePropaga === void 0 ? false : _ref$immediatePropaga;
  if (preventDefault) {
    event.preventDefault();
  }
  if (propagation) {
    event.stopPropagation();
  }
  if (immediatePropagation) {
    event.stopImmediatePropagation();
  }
};

// Helper method to convert a component/directive name to a base event name
// `getBaseEventName('BNavigationItem')` => 'navigation-item'
// `getBaseEventName('BVToggle')` => 'toggle'
var getBaseEventName = function getBaseEventName(value) {
  return kebabCase(value.replace(RX_BV_PREFIX, ''));
};

// Get a root event name by component/directive and event name
// `getBaseEventName('BModal', 'show')` => 'bv::modal::show'
export var getRootEventName = function getRootEventName(name, eventName) {
  return [ROOT_EVENT_NAME_PREFIX, getBaseEventName(name), eventName].join(ROOT_EVENT_NAME_SEPARATOR);
};

// Get a root action event name by component/directive and action name
// `getRootActionEventName('BModal', 'show')` => 'bv::show::modal'
export var getRootActionEventName = function getRootActionEventName(name, actionName) {
  return [ROOT_EVENT_NAME_PREFIX, actionName, getBaseEventName(name)].join(ROOT_EVENT_NAME_SEPARATOR);
};