/**
 * this module contains all the helper methods for dom manipulation or access
 * @module utils/dom
 * @author Aamir khan
 */

import assign from "lodash/assign";
import isElement from "lodash/isElement";
import split from "lodash/split";
import { yell } from "./common";



/**
 * a jquery like css dom selector which returns dom node
 * @param {string} selector - css selector
 * @returns {DOMElement} dom node
 */
export const select = document.querySelector.bind(document);


/**
 * creates a new dom element
 * @param {string} tagName - tag name of the element
 * @returns {DOMElement} dom node
 */
export const newElement = document.createElement.bind(document);


/**
 * add an even listener to an element given by the selector
 * @param {String} selector a css selector along with the event name seperated by a colon
 * @param {Function} handler function to be called when the event is triggered
 * @returns {Function} function to remove the event listener
 * @example
 * // specify the css selector followed by the event name with semilcolon in between
  const removePlayClick = on('#play:click', () => player.play());
  // to add listener on gloal document
  on(':keydown', (e) => {{);
 * 
 */
export const on = (selector, handler, node) => {
  if(isElement(node)){
    node.addEventListener(selector, handler);
    return () => node.removeEventListener(selector, handler);
  }

  const [s, event] = split(selector, ':');
  const el = s ? select(s) : document;
  el.addEventListener(event, handler);
  return () => el.removeEventListener(event, handler);
}


/**
 * dispatch a custom event on document object
 * @param {String} evtName - custom event name
 * @param {Object} data - data thay you want to pass to the event listener
 * @param {Object} options - options to pass while creating the custom event
 */
export const dispatchCustomEvent = (evtName, data, options) => {
  const opt = options || { bubbles: false };
  const evt = new CustomEvent(evtName,
    assign({}, opt, { detail: data }));
  document.dispatchEvent(evt);
};



/**
 * load a script from the given url
 * @author Aamir Khan
 * @param {String} src - url of the script
 * @param {Function} onload - callback function to be called when the script is loaded
 */
export const addScript = (src, onload) => {
  const script = newElement('script');
  script.src = src;
  script.type = 'text/javascript';
  script.onerror = yell(`Failed to load ${src}`);
  script.async = false;
  script.onload = onload;
  select('head').appendChild(script);
}