"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.astToEsQueryString = void 0;

var _date_format = require("./date_format");

var _date_value = require("./date_value");

var _ast = require("./ast");

var _predicate = require("../../../services/predicate");

/*
 * SPDX-License-Identifier: Apache-2.0
 *
 * The OpenSearch Contributors require contributions made to
 * this file be licensed under the Apache-2.0 license or a
 * compatible open source license.
 *
 * Modifications Copyright OpenSearch Contributors. See
 * GitHub history for details.
 */

/*
 * Licensed to Elasticsearch B.V. under one or more contributor
 * license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright
 * ownership. Elasticsearch B.V. licenses this file to you under
 * the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
var emitMatch = function emitMatch(match) {
  if (!match) {
    return '';
  }

  return _ast.AST.Match.isMust(match) ? '+' : '-';
};

var escapeValue = function escapeValue(value) {
  if (typeof value === 'string') {
    return value.replace(/([\\"])/g, '\\$1');
  }

  return value;
};

var emitFieldDateLikeClause = function emitFieldDateLikeClause(field, value, operator, match) {
  var matchOp = emitMatch(match);

  switch (operator) {
    case _ast.Operator.EQ:
      return "".concat(matchOp).concat(field, ":").concat((0, _date_format.printIso8601)(value));

    case _ast.Operator.GT:
      return "".concat(matchOp).concat(field, ":>").concat((0, _date_format.printIso8601)(value));

    case _ast.Operator.GTE:
      return "".concat(matchOp).concat(field, ":>=").concat((0, _date_format.printIso8601)(value));

    case _ast.Operator.LT:
      return "".concat(matchOp).concat(field, ":<").concat((0, _date_format.printIso8601)(value));

    case _ast.Operator.LTE:
      return "".concat(matchOp).concat(field, ":<=").concat((0, _date_format.printIso8601)(value));

    default:
      throw new Error("unknown operator [".concat(operator, "]"));
  }
};

var emitFieldDateValueClause = function emitFieldDateValueClause(field, value, operator, match) {
  var matchOp = emitMatch(match);
  var granularity = value.granularity,
      resolve = value.resolve;
  var date = resolve();

  if (granularity) {
    switch (operator) {
      case _ast.Operator.EQ:
        var gte = granularity.iso8601(granularity.start(date));
        var lt = granularity.iso8601(granularity.startOfNext(date));
        return "".concat(matchOp).concat(field, ":(>=").concat(gte, " AND <").concat(lt, ")");

      case _ast.Operator.GT:
        return "".concat(matchOp).concat(field, ":>=").concat(granularity.iso8601(granularity.startOfNext(date)));

      case _ast.Operator.GTE:
        return "".concat(matchOp).concat(field, ":>=").concat(granularity.iso8601(granularity.start(date)));

      case _ast.Operator.LT:
        return "".concat(matchOp).concat(field, ":<").concat(granularity.iso8601(granularity.start(date)));

      case _ast.Operator.LTE:
        return "".concat(matchOp).concat(field, ":<").concat(granularity.iso8601(granularity.startOfNext(date)));

      default:
        throw new Error("unknown operator [".concat(operator, "]"));
    }
  }

  return emitFieldDateLikeClause(field, date, operator, match);
};

var emitFieldNumericClause = function emitFieldNumericClause(field, value, operator, match) {
  var matchOp = emitMatch(match);

  switch (operator) {
    case _ast.Operator.EQ:
      return "".concat(matchOp).concat(field, ":").concat(value);

    case _ast.Operator.GT:
      return "".concat(matchOp).concat(field, ":>").concat(value);

    case _ast.Operator.GTE:
      return "".concat(matchOp).concat(field, ":>=").concat(value);

    case _ast.Operator.LT:
      return "".concat(matchOp).concat(field, ":<").concat(value);

    case _ast.Operator.LTE:
      return "".concat(matchOp).concat(field, ":<=").concat(value);

    default:
      throw new Error("unknown operator [".concat(operator, "]"));
  }
};

var emitFieldStringClause = function emitFieldStringClause(field, value, match) {
  var matchOp = emitMatch(match);

  if (value.match(/\s/)) {
    return "".concat(matchOp).concat(field, ":\"").concat(escapeValue(value), "\"");
  }

  return "".concat(matchOp).concat(field, ":").concat(escapeValue(value));
};

var emitFieldBooleanClause = function emitFieldBooleanClause(field, value, match) {
  var matchOp = emitMatch(match);
  return "".concat(matchOp).concat(field, ":").concat(value);
};

var emitFieldSingleValueClause = function emitFieldSingleValueClause(field, value, operator, match) {
  if ((0, _date_value.isDateValue)(value)) {
    return emitFieldDateValueClause(field, value, operator, match);
  }

  if ((0, _predicate.isDateLike)(value)) {
    return emitFieldDateLikeClause(field, value, operator, match);
  }

  if ((0, _predicate.isString)(value)) {
    return emitFieldStringClause(field, value, match);
  }

  if ((0, _predicate.isNumber)(value)) {
    return emitFieldNumericClause(field, value, operator, match);
  }

  if ((0, _predicate.isBoolean)(value)) {
    return emitFieldBooleanClause(field, value, match);
  }

  throw new Error("unknown type of field value [".concat(value, "]"));
};

var emitFieldClause = function emitFieldClause(clause, isGroupMember) {
  var field = clause.field,
      value = clause.value,
      operator = clause.operator;
  var match = clause.match;

  if (isGroupMember && _ast.AST.Match.isMust(match)) {
    match = undefined;
  }

  if (!(0, _predicate.isArray)(value)) {
    return emitFieldSingleValueClause(field, value, operator, match);
  }

  var matchOp = emitMatch(match);
  var clauses = value.map(function (v) {
    return emitFieldSingleValueClause(field, v, operator);
  }).join(' OR ');
  return "".concat(matchOp, "(").concat(clauses, ")");
};

var emitTermClause = function emitTermClause(clause, isGroupMember) {
  var value = clause.value;
  var match = clause.match;

  if (isGroupMember && _ast.AST.Match.isMust(match)) {
    match = undefined;
  }

  var matchOp = emitMatch(match);
  return "".concat(matchOp).concat(escapeValue(value));
};

var emitIsClause = function emitIsClause(clause, isGroupMember) {
  var flag = clause.flag,
      match = clause.match;
  var matchOp = isGroupMember ? '' : '+';

  var flagValue = _ast.AST.Match.isMust(match);

  return "".concat(matchOp).concat(flag, ":").concat(flagValue);
};

var emitGroupClause = function emitGroupClause(clause) {
  var value = clause.value;
  var formattedValues = value.map(function (clause) {
    return emitClause(clause, true);
  });
  return "+(".concat(formattedValues.join(' '), ")");
};

function emitClause(clause) {
  var isGroupMember = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;

  if (_ast.AST.Field.isInstance(clause)) {
    return emitFieldClause(clause, isGroupMember);
  }

  if (_ast.AST.Term.isInstance(clause)) {
    return emitTermClause(clause, isGroupMember);
  }

  if (_ast.AST.Is.isInstance(clause)) {
    return emitIsClause(clause, isGroupMember);
  }

  if (_ast.AST.Group.isInstance(clause)) {
    return emitGroupClause(clause);
  }

  throw new Error("unknown clause type [".concat(JSON.stringify(clause), "]"));
}

var astToEsQueryString = function astToEsQueryString(ast) {
  if (ast.clauses.length === 0) {
    return '*';
  }

  return ast.clauses.map(function (clause) {
    return emitClause(clause);
  }).join(' ');
};

exports.astToEsQueryString = astToEsQueryString;