/**
 * Перетинає два масиви
 *
 * @example
 * // returns [1, 4, 5, 6]
 * intersect([1,2,3,4,5,6],[1,4,5,6,7,8,9,11])
 * @param {Array} a
 * @param {Array} b
 * @returns {Array} Returns new intersect array
 */
function intersect(a, b) {
  let aN = a; let bN = b;
  if (b.length > a.length) {
    [aN, bN] = [bN, aN];
  }
  return aN.filter((e) => bN.includes(e));
}

/**
 * Створення шаблона або його частини внаслідок перевірки значення із веб-запиту та заздалегідь прописаного значення.
 * Дозволяє змінювати наповнення сторінки через ряд перевірок. Є можливість внесення додаткової умови - що робити, коли умова не виконується.
 *
 * @summary Перевірка двох значень та виконання коду при виконанні умови, а також у всіх інших випадках.
 * @priority 5
 * @alias ifCond
 * @type helper
 * @tag condition
 * @example
 * {{#ifCond @root.req.domain 'in' 'help.softpro.ua,123'}} {{select user.uid data="get_full_uid"}} {{^}} Умова не виконана {{/ifCond}}
 * @example
 * {{#ifCond "1234567890" 'in' @root.user.group_list}} 1=1 {{^}} uid='{{uid}}' {{/ifCond}}
 * @example
 * {{#ifCond 'debug' 'in' @root.setting.core.setting}}Умова виконана{{^}}Не виконана умова{{/ifCond}}
 * @param {Array} args Параметри для значень і умов
 * @param {Array} args[0]] Перше значення
 * @param {Array} args[1]] Оператор
 * @param {Array} args[2]] Друге значення
 * @returns {String} Returns HTML
 */
export default function ifCond(v1, operator, v2, options) {
  const __obj = this;

  switch (operator) {
    case '==':
      return (v1 == v2) ? options.fn(__obj) : options.inverse(__obj);
    case '!=':
      return (v1 != v2) ? options.fn(__obj) : options.inverse(__obj);
    case '===':
      return (v1 === v2) ? options.fn(__obj) : options.inverse(__obj);
    case '!==':
      return (v1 !== v2) ? options.fn(__obj) : options.inverse(__obj);
    case '&&':
      return (v1 && v2) ? options.fn(__obj) : options.inverse(__obj);
    case '||':
      return (v1 || v2) ? options.fn(__obj) : options.inverse(__obj);
    case '<':
      return (v1 < v2) ? options.fn(__obj) : options.inverse(__obj);
    case '<=':
      return (v1 <= v2) ? options.fn(__obj) : options.inverse(__obj);
    case '>':
      return (v1 > v2) ? options.fn(__obj) : options.inverse(__obj);
    case '>=':
      return (v1 >= v2) ? options.fn(__obj) : options.inverse(__obj);
    case '&':
      return intersect(v1, v2).length !== 0
        ? options.fn(__obj)
        : options.inverse(__obj);
    case '!~':
      return (v1 || '').indexOf(v2) === -1
        ? options.fn(__obj)
        : options.inverse(__obj);
    case '~':
      return (v1 || '').indexOf(v2) !== -1
        ? options.fn(__obj)
        : options.inverse(__obj);
    case 'period':
      return (new Date(v1) < new Date() && new Date(v2) > new Date())
        ? options.fn(__obj)
        : options.inverse(__obj);
    case 'in': {
      if (typeof v2 === 'string') v2 = v2.split(',').map(item => item.trim());

      if (Array.isArray(v1)) {
        return v1.some((value) => v2.includes(value.toString()))
          ? options.fn(__obj)
          : options.inverse(__obj);
      }
      return v2.includes(v1?.toString())
        ? options.fn(__obj)
        : options.inverse(__obj);
    }
    case 'not in': {
      if (typeof v2 === 'string') v2 = v2.split(',').map(item => item.trim());
      return !v2.includes(v1?.toString())
        ? options.fn(__obj)
        : options.inverse(__obj);
    }
    default:
      return options.inverse(__obj);
  }
}
