import { isArray, map, keys, hasOwn, isObject, isArrayLike, isString, isRegExp, isNumber } from "../../../../../zrender@5.4.4/node_modules/zrender/lib/core/util.mjs";
import { makePrintable, throwError } from "./log.mjs";
import { getRawValueParser, createFilterComparator } from "../data/helper/dataValueHelper.mjs";
var RELATIONAL_EXPRESSION_OP_ALIAS_MAP = {
  value: "eq",
  // PENDING: not good for literal semantic?
  "<": "lt",
  "<=": "lte",
  ">": "gt",
  ">=": "gte",
  "=": "eq",
  "!=": "ne",
  "<>": "ne"
  // Might be misleading for sake of the difference between '==' and '===',
  // so don't support them.
  // '==': 'eq',
  // '===': 'seq',
  // '!==': 'sne'
  // PENDING: Whether support some common alias "ge", "le", "neq"?
  // ge: 'gte',
  // le: 'lte',
  // neq: 'ne',
};
var RegExpEvaluator = (
  /** @class */
  function() {
    function RegExpEvaluator2(rVal) {
      var condValue = this._condVal = isString(rVal) ? new RegExp(rVal) : isRegExp(rVal) ? rVal : null;
      if (condValue == null) {
        var errMsg = "";
        if (process.env.NODE_ENV !== "production") {
          errMsg = makePrintable("Illegal regexp", rVal, "in");
        }
        throwError(errMsg);
      }
    }
    RegExpEvaluator2.prototype.evaluate = function(lVal) {
      var type = typeof lVal;
      return isString(type) ? this._condVal.test(lVal) : isNumber(type) ? this._condVal.test(lVal + "") : false;
    };
    return RegExpEvaluator2;
  }()
);
var ConstConditionInternal = (
  /** @class */
  function() {
    function ConstConditionInternal2() {
    }
    ConstConditionInternal2.prototype.evaluate = function() {
      return this.value;
    };
    return ConstConditionInternal2;
  }()
);
var AndConditionInternal = (
  /** @class */
  function() {
    function AndConditionInternal2() {
    }
    AndConditionInternal2.prototype.evaluate = function() {
      var children = this.children;
      for (var i = 0; i < children.length; i++) {
        if (!children[i].evaluate()) {
          return false;
        }
      }
      return true;
    };
    return AndConditionInternal2;
  }()
);
var OrConditionInternal = (
  /** @class */
  function() {
    function OrConditionInternal2() {
    }
    OrConditionInternal2.prototype.evaluate = function() {
      var children = this.children;
      for (var i = 0; i < children.length; i++) {
        if (children[i].evaluate()) {
          return true;
        }
      }
      return false;
    };
    return OrConditionInternal2;
  }()
);
var NotConditionInternal = (
  /** @class */
  function() {
    function NotConditionInternal2() {
    }
    NotConditionInternal2.prototype.evaluate = function() {
      return !this.child.evaluate();
    };
    return NotConditionInternal2;
  }()
);
var RelationalConditionInternal = (
  /** @class */
  function() {
    function RelationalConditionInternal2() {
    }
    RelationalConditionInternal2.prototype.evaluate = function() {
      var needParse = !!this.valueParser;
      var getValue = this.getValue;
      var tarValRaw = getValue(this.valueGetterParam);
      var tarValParsed = needParse ? this.valueParser(tarValRaw) : null;
      for (var i = 0; i < this.subCondList.length; i++) {
        if (!this.subCondList[i].evaluate(needParse ? tarValParsed : tarValRaw)) {
          return false;
        }
      }
      return true;
    };
    return RelationalConditionInternal2;
  }()
);
function parseOption(exprOption, getters) {
  if (exprOption === true || exprOption === false) {
    var cond = new ConstConditionInternal();
    cond.value = exprOption;
    return cond;
  }
  var errMsg = "";
  if (!isObjectNotArray(exprOption)) {
    if (process.env.NODE_ENV !== "production") {
      errMsg = makePrintable("Illegal config. Expect a plain object but actually", exprOption);
    }
    throwError(errMsg);
  }
  if (exprOption.and) {
    return parseAndOrOption("and", exprOption, getters);
  } else if (exprOption.or) {
    return parseAndOrOption("or", exprOption, getters);
  } else if (exprOption.not) {
    return parseNotOption(exprOption, getters);
  }
  return parseRelationalOption(exprOption, getters);
}
function parseAndOrOption(op, exprOption, getters) {
  var subOptionArr = exprOption[op];
  var errMsg = "";
  if (process.env.NODE_ENV !== "production") {
    errMsg = makePrintable('"and"/"or" condition should only be `' + op + ": [...]` and must not be empty array.", "Illegal condition:", exprOption);
  }
  if (!isArray(subOptionArr)) {
    throwError(errMsg);
  }
  if (!subOptionArr.length) {
    throwError(errMsg);
  }
  var cond = op === "and" ? new AndConditionInternal() : new OrConditionInternal();
  cond.children = map(subOptionArr, function(subOption) {
    return parseOption(subOption, getters);
  });
  if (!cond.children.length) {
    throwError(errMsg);
  }
  return cond;
}
function parseNotOption(exprOption, getters) {
  var subOption = exprOption.not;
  var errMsg = "";
  if (process.env.NODE_ENV !== "production") {
    errMsg = makePrintable('"not" condition should only be `not: {}`.', "Illegal condition:", exprOption);
  }
  if (!isObjectNotArray(subOption)) {
    throwError(errMsg);
  }
  var cond = new NotConditionInternal();
  cond.child = parseOption(subOption, getters);
  if (!cond.child) {
    throwError(errMsg);
  }
  return cond;
}
function parseRelationalOption(exprOption, getters) {
  var errMsg = "";
  var valueGetterParam = getters.prepareGetValue(exprOption);
  var subCondList = [];
  var exprKeys = keys(exprOption);
  var parserName = exprOption.parser;
  var valueParser = parserName ? getRawValueParser(parserName) : null;
  for (var i = 0; i < exprKeys.length; i++) {
    var keyRaw = exprKeys[i];
    if (keyRaw === "parser" || getters.valueGetterAttrMap.get(keyRaw)) {
      continue;
    }
    var op = hasOwn(RELATIONAL_EXPRESSION_OP_ALIAS_MAP, keyRaw) ? RELATIONAL_EXPRESSION_OP_ALIAS_MAP[keyRaw] : keyRaw;
    var condValueRaw = exprOption[keyRaw];
    var condValueParsed = valueParser ? valueParser(condValueRaw) : condValueRaw;
    var evaluator = createFilterComparator(op, condValueParsed) || op === "reg" && new RegExpEvaluator(condValueParsed);
    if (!evaluator) {
      if (process.env.NODE_ENV !== "production") {
        errMsg = makePrintable('Illegal relational operation: "' + keyRaw + '" in condition:', exprOption);
      }
      throwError(errMsg);
    }
    subCondList.push(evaluator);
  }
  if (!subCondList.length) {
    if (process.env.NODE_ENV !== "production") {
      errMsg = makePrintable("Relational condition must have at least one operator.", "Illegal condition:", exprOption);
    }
    throwError(errMsg);
  }
  var cond = new RelationalConditionInternal();
  cond.valueGetterParam = valueGetterParam;
  cond.valueParser = valueParser;
  cond.getValue = getters.getValue;
  cond.subCondList = subCondList;
  return cond;
}
function isObjectNotArray(val) {
  return isObject(val) && !isArrayLike(val);
}
var ConditionalExpressionParsed = (
  /** @class */
  function() {
    function ConditionalExpressionParsed2(exprOption, getters) {
      this._cond = parseOption(exprOption, getters);
    }
    ConditionalExpressionParsed2.prototype.evaluate = function() {
      return this._cond.evaluate();
    };
    return ConditionalExpressionParsed2;
  }()
);
function parseConditionalExpression(exprOption, getters) {
  return new ConditionalExpressionParsed(exprOption, getters);
}
export {
  parseConditionalExpression
};
