'use strict';

var _defineProperty = require('@babel/runtime/helpers/defineProperty');
var _toConsumableArray = require('@babel/runtime/helpers/toConsumableArray');
require('core-js/modules/es.symbol.js');
require('core-js/modules/es.array.concat.js');
require('core-js/modules/es.array.filter.js');
require('core-js/modules/es.array.splice.js');
require('core-js/modules/es.object.get-own-property-descriptor.js');
require('core-js/modules/es.object.get-own-property-descriptors.js');
require('core-js/modules/es.object.keys.js');
require('core-js/modules/es.object.to-string.js');
require('core-js/modules/es.regexp.exec.js');
require('core-js/modules/es.regexp.to-string.js');
require('core-js/modules/es.string.pad-start.js');
require('core-js/modules/es.string.replace.js');
require('core-js/modules/web.dom-collections.for-each.js');

function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }

var _defineProperty__default = /*#__PURE__*/_interopDefault(_defineProperty);
var _toConsumableArray__default = /*#__PURE__*/_interopDefault(_toConsumableArray);

function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty__default.default(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
/**
 * RuleBuilder helper function to traverse the tree and find the indicies needed to create
 * a path to the given rule ID
 *
 * @param {array} arr The RuleBuilder tree rules array
 * @param {string} id The id of the rule to find in the tree
 * @param {array} parentIndex an array of ints storing the parent indices in the path
 */
var findRulePathById = function findRulePathById(arr, id) {
  var parentIndex = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
  if (!Array.isArray(arr)) {
    return [];
  }
  return arr.reduce(function (i, rule, index) {
    if (Array.isArray(i) && i.length > 0) {
      return i;
    }
    if (rule.id === id) {
      return [].concat(_toConsumableArray__default.default(i), _toConsumableArray__default.default(parentIndex), [index]);
    }
    if (rule.rules) {
      return findRulePathById(rule.rules, id, [].concat(_toConsumableArray__default.default(parentIndex), [index]));
    }
    return i;
  }, []);
};

/**
 * RuleBuilder helper function to filter a rule out of the tree by ID
 *
 * @param {array} arr The RuleBuilder tree rules
 * @param {string} id The ID of the rule to filter out of the tree
 */
var filterRulesById = function filterRulesById(arr, id) {
  if (!Array.isArray(arr)) {
    return [];
  }
  return arr.reduce(function (carry, rule) {
    if (rule.rules && rule.rules.length) {
      var rules = filterRulesById(rule.rules, id);
      if (rules.length) {
        return [].concat(_toConsumableArray__default.default(carry), [_objectSpread(_objectSpread({}, rule), {}, {
          rules: rules
        })]);
      }
    } else if (rule.id !== id) {
      return [].concat(_toConsumableArray__default.default(carry), [rule]);
    }
    return carry;
  }, []);
};

/**
 * RuleBuilder helper function to insert a new rule into the tree after the given path
 *
 * @param {array} arr RuleBuilder tree rules
 * @param {object} rule The rule object to be inserted into the tree
 * @param {array} path The array of indicies making a path to the location after which the rule should be inserted
 */
var insertRuleAfterPath = function insertRuleAfterPath(arr, rule, path) {
  if (!Array.isArray(path) || !Array.isArray(arr)) {
    return undefined;
  }
  var insertionPoint = path.pop() + 1;
  var current = arr;
  for (var i = 0; i < path.length; i += 1) {
    if (current[path[i]] && current[path[i]].rules) {
      current = current[path[i]].rules;
    } else {
      throw new Error('INVALID_PATH_FOR_RULE_TREE');
    }
  }
  current.splice(insertionPoint, 0, rule);
  return _toConsumableArray__default.default(arr);
};

/**
 * RuleBuilder helper function to update the rule at the given path in the tree
 *
 * @param {array} arr RuleBuilder tree rules
 * @param {object} rule The new rule object to replace the existing
 * @param {array} path The array of indicies making a path to the location after which the rule should be inserted
 */
var updateRuleAtPath = function updateRuleAtPath(arr, rule, path) {
  var updatePoint = path.pop();
  var current = arr;
  for (var i = 0; i < path.length; i += 1) {
    current = current[path[i]].rules;
  }
  current.splice(updatePoint, 1, rule);
  return _toConsumableArray__default.default(arr);
};

/**
 *
 * @param {array} arr Array of rules from the RuleBuilder tree
 * @param {array} path Array of indicies that define the path down the rule tree to grab a specific rule.
 */
var getRuleByPath = function getRuleByPath(arr, path) {
  if (!Array.isArray(path) || !Array.isArray(arr)) {
    return undefined;
  }
  return path.reduce(function (carry, part) {
    if (carry && carry[part]) {
      return carry && carry[part];
    }
    if (carry && carry.rules[part]) {
      return carry && carry.rules[part];
    }
    return undefined;
  }, arr);
};

/**
 * Generates a new empty rule
 */
var generateRule = function generateRule() {
  return {
    id: Math.random().toString(36).substring(2, 12).padStart(10, '0'),
    columnId: '',
    operand: '',
    value: ''
  };
};

/**
 * Generates a new rule group with one default rule
 */
var generateRuleGroup = function generateRuleGroup() {
  return {
    id: Math.random().toString(36).substring(2, 12).padStart(10, '0'),
    groupLogic: 'ALL',
    rules: [generateRule()]
  };
};

/**
 * Helper function to insert a new rule or group after the given ID. Searches the
 * rules tree to find the rule with the given ID, and uses that path to insert a new rule (or group)
 * after it.
 *
 * @param {array} arr RuleBuilder tree rules array
 * @param {string} ruleId The rule id after which the new rule should
 * @param {boolean} isGroup Is the new rule being added a group or an individual rule
 */
var addRule = function addRule(arr, ruleId) {
  var isGroup = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
  var generate = isGroup ? generateRuleGroup : generateRule;
  if (ruleId) {
    var rulePath = findRulePathById(arr, ruleId);
    return insertRuleAfterPath(_toConsumableArray__default.default(arr), generate(), rulePath);
  }
  return [].concat(_toConsumableArray__default.default(arr), [generate()]);
};
var slugify = function slugify(text) {
  if (!text) {
    return '';
  }
  return text.toString().toLowerCase().replace(/\s+/g, '-') // Replace spaces with -
  .replace(/[^\w-]+/g, '') // Remove all non-word chars
  .replace(/--+/g, '-') // Replace multiple - with single -
  .replace(/^-+/, '') // Trim - from start of text
  .replace(/-+$/, ''); // Trim - from end of text
};

exports.addRule = addRule;
exports.filterRulesById = filterRulesById;
exports.findRulePathById = findRulePathById;
exports.generateRule = generateRule;
exports.generateRuleGroup = generateRuleGroup;
exports.getRuleByPath = getRuleByPath;
exports.insertRuleAfterPath = insertRuleAfterPath;
exports.slugify = slugify;
exports.updateRuleAtPath = updateRuleAtPath;
