'use strict';

const InterceptorHandler = require('./InterceptorHandler-09a1e84b.js');

class VisibilityHandler extends InterceptorHandler.InterceptorHandler {
  run(context, values, field, value, boundField) {
    return { value: values[boundField.id], visible: this.shouldShow(context, values, field, value) };
  }
}

function doesSatisfyRule(rule, data) {
  if (!rule || !data) {
    return true;
  }
  if (rule.type === 'group') {
    if (!rule.rules || rule.rules.length === 0) {
      return true;
    }
    for (let i = 0; i < (rule.rules || []).length; i++) {
      const satisfies = doesSatisfyRule(rule.rules[i], data);
      if (satisfies && rule.operator === 'or') {
        // return true if any rule satisfies in 'or'
        return true;
      }
      else if (!satisfies && rule.operator === 'and') {
        // return false if any rule doesn't satisfy in 'and'
        return false;
      }
      else if (satisfies && rule.operator === 'and' && i === rule.rules.length - 1) {
        // return true if the last rule satisfies in 'and'
        return true;
      }
    }
  }
  else if (rule.type === 'condition') {
    const { condition, value, key } = rule;
    if (!condition || !key) {
      // condition is not valid
      return false;
    }
    switch (condition) {
      case 'eq': {
        switch (typeof data[key]) {
          case 'boolean': {
            // tslint:disable-next-line
            return data[key] == value;
          }
          case 'number': {
            // tslint:disable-next-line
            return data[key] == value;
          }
          case 'string': {
            // tslint:disable-next-line
            return (data[key] || '').trim() == (value || '').trim();
          }
        }
        return false;
      }
      case 'ne': {
        switch (typeof data[key]) {
          case 'boolean': {
            // tslint:disable-next-line
            return data[key] != value;
          }
          case 'number': {
            // tslint:disable-next-line
            return data[key] != value;
          }
          case 'string': {
            // tslint:disable-next-line
            return (data[key] || '').trim() != (value || '').trim();
          }
        }
        return false;
      }
    }
  }
  return false;
}

class ConcealerConditional extends InterceptorHandler.InterceptorConfig {
  constructor(rule) {
    super('concealerGenericRule');
    this.rule = rule;
  }
}
ConcealerConditional.id = 'concealerGenericRule';
class ConcealerGenericRuleHandler extends VisibilityHandler {
  constructor(config) {
    super();
    this.config = config;
  }
  shouldShow(_context, values, _field, _value) {
    return doesSatisfyRule(this.config.rule, values);
  }
}
InterceptorHandler.registerInterceptor(ConcealerConditional.id, (config) => new ConcealerGenericRuleHandler(config));

class Rule {
  constructor(type) {
    this.type = type;
  }
}

class Equal extends Rule {
  constructor(key, value) {
    super('condition');
    this.condition = 'eq';
    this.key = key;
    this.value = value;
  }
}

exports.ConcealerConditional = ConcealerConditional;
exports.Equal = Equal;
