Source: utils/index.js

/* eslint-disable no-useless-escape */
const LOGGER_FNS = [
  ['error', (...props) => { console && console.error(...props); }], // eslint-disable-line no-console
  ['warn', (...props) => { console && console.warn(...props); }], // eslint-disable-line no-console
  ['info', (...props) => { console && console.info(...props); }], // eslint-disable-line no-console
  ['debug', (...props) => { console && console.log(...props); }], // eslint-disable-line no-console
];

export getPlainText from './getPlainText';

/**
 * Cria logger
 * 0 - Error
 * 1 - Warn
 * 2 - Info
 * 3 - Debug
 */
export const createLogger = (level = 0) => {
  const logger = {};
  LOGGER_FNS.forEach(([logMethod, fn], i) => {
    logger[logMethod] = level >= i ? fn : () => { };
  });
  return logger;
};

/**
 * Pega o browser e possivelmente a versão do navegador
 * @returns {object}
 */
const getBrowser = () => {
  const ua = navigator.userAgent;

  let temp;
  let matches = ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];

  if (/trident/i.test(matches[1])) {
    temp = /\brv[ :]+(\d+)/g.exec(ua) || [];
    return { name: 'IE', version: (temp[1] || '') };
  }

  if (matches[1] === 'Chrome') {
    temp = ua.match(/\bOPR\/(\d+)/);
    if (temp) return { name: 'Opera ', version: temp[1] };
  }

  matches = matches[2] ?
    [matches[1], matches[2]] :
    [navigator.appName, navigator.appVersion, '-?'];
  temp = ua.match(/version\/(\d+)/i);

  if (temp) matches.splice(1, 1, temp[1]);
  return { name: matches[0], version: matches.splice(1, matches.length).join('') };
};

/**
 * Verifica se o device é mobile
 * @returns {boolean}
 */
const checkIsMobile = () => {
  const a = navigator.userAgent || navigator.vendor || window.opera;
  return (a.match(/Android/i) || a.match(/webOS/i) || a.match(/iPhone/i) || a.match(/iPad/i) || a.match(/iPod/i) || a.match(/BlackBerry/i) || a.match(/Windows Phone/i));
};

/**
 * Retorna o sistema operacional
 * @returns {string}
 */
const getOS = () => {
  const OSS = [
    {
      string: navigator.platform,
      subString: 'Win',
      identity: 'Windows'
    }, {
      string: navigator.platform,
      subString: 'Mac',
      identity: 'Mac'
    }, {
      string: navigator.userAgent,
      subString: 'iPhone',
      identity: 'iPhone/iPod'
    }, {
      string: navigator.platform,
      subString: 'Linux',
      identity: 'Linux'
    }
  ];

  let currentOS;
  OSS.forEach((os) => {
    if (!currentOS && os.string.indexOf(os.subString) !== -1) currentOS = os.identity;
  });
  return currentOS;
};

/**
 * Captura informações do dispositivo
 */
export const getDeviceInfo = () => {
  const browser = getBrowser();
  const isMobile = checkIsMobile();

  return {
    isMobile,
    browserName: browser.name,
    browserVersion: browser.version,
    operatingSystem: getOS(),
  };
};

/**
 * Element.matches pollyfill
 */
const ElementMatches = Element.prototype.matches ||
  Element.prototype.matchesSelector ||
  Element.prototype.mozMatchesSelector ||
  Element.prototype.msMatchesSelector ||
  Element.prototype.oMatchesSelector ||
  Element.prototype.webkitMatchesSelector ||
  (function (s) {
    const matches = (this.parentNode || this.parentElement).querySelectorAll(s);
    return matches.filter(match => match === this).length > 0;
  });

/**
 * Verifica se o elemento é filho de uma determinada query
 * @param elem - Elemento DOM
 * @param query - Exemplo: .className div
 * @return {boolean}
 */
export const isChildren = (elem, query) => {
  if (!elem.parentNode) return false;
  if (ElementMatches.bind(elem)(query)) return true;
  return isChildren(elem.parentNode, query);
};

/**
 * Pega o elemento pai com a tag <a> de um determinado elemento
 * @param elem - Elemento DOM
 * @return elemento <a> pai
 */
export const getMainLinkElement = (element) => {
  if (element.tagName == 'A')
    return element;
  else if (element.parentElement)
    return getMainLinkElement(element.parentElement);
  return null;
};

export const checkException = (exceptions, elem, index = 0) => {
  const q = exceptions[index];
  if (!q) return true;
  return !isChildren(elem, q) && checkException(exceptions, elem, index + 1);
};

/**
 * Detecta swipe no mobile
 * @param el
 * @param callback
 * @param swipeThreshold
 * @param swipeRestraint
 * @param swipeAllowedTime
 */
export const swipeDetect = (el, callback, swipeThreshold = 100, swipeRestraint = 50, swipeAllowedTime = 1000) => {
  let swipedir;
  let startX;
  let startY;
  let distX;
  let distY;
  let startTime;
  let elapsedTime;

  el.addEventListener('touchstart', (e) => {
    const touchobj = e.changedTouches[0];
    swipedir = 'none';
    startX = touchobj.pageX;
    startY = touchobj.pageY;
    distX = 0;
    distY = 0;
    startTime = new Date().getTime();
  }, true);

  el.addEventListener('touchend', (e) => {
    const touchobj = e.changedTouches[0];
    distX = touchobj.pageX - startX;
    distY = touchobj.pageY - startY;
    elapsedTime = new Date().getTime() - startTime;
    if (elapsedTime <= swipeAllowedTime) {
      if (Math.abs(distX) >= swipeThreshold && Math.abs(distY) <= swipeRestraint) swipedir = (distX < 0) ? 'left' : 'right';
    }
    callback && callback(swipedir);
  }, true);
};


/**
 * Verifica se um texto é uma url
 * @param {*} text - Texto a ser verificado
 * @returns {boolean} - Verdadeiro para url ou falso para texti
 */
export const isValidUrl = (text) => {
  let match = text.match(/^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\(\)\*\+,;=.]+$/gm);
  return match && match.length != 0;
};

/**
* Pega o id de um vídeo do youtube
* @param src - Source do vídeo
*/
export const getYtId = (src) => {
  const match = src.match(/(youtu\.be\/|youtube\.com\/(watch\?(.*&)?v=|(embed|v)\/))([^?&"'>]+)/);
  return match && match.length >= 5 ? match[5] : null;
};