// Generated by CoffeeScript 2.3.2
(function() {
  // the job of the search semantic module is to create the actual elasticsearch query from the
  // request query parameters.

  // This module does not do much itself. Instead, it gathers a list of QueryBuilders from the
  // configuration, passes them the current type and query and lets them construct the parts of
  // the elasticsearch query.

  // The results of all query builders are merged and returned.

  var ConfigNode, FilterQuery, Merger, MultiMatchQuery, SearchSemantics, call, isArray, merge, warningsIssued;

  ({ConfigNode, Merger} = require("@l.degener/irma-config"));

  MultiMatchQuery = require("./multi-match-query");

  FilterQuery = require("./filter-query");

  ({isArray} = require("util"));

  call = require("../call");

  merge = Merger({
    customMerge: function(lhs, rhs, pass) {
      if (isArray(lhs) && isArray(rhs)) {
        return lhs.concat(rhs);
      } else {
        return pass;
      }
    }
  });

  warningsIssued = {};

  module.exports = SearchSemantics = class SearchSemantics extends ConfigNode {
    dependencies() {
      return {
        io: ["/", "io"]
      };
    }

    init({io}) {
      var issueWarning, normalizeOutput;
      issueWarning = function(msg) {
        if (!warningsIssued[msg]) {
          warningsIssued[msg] = true;
          return io.console.warn(msg);
        }
      };
      issueWarning("WARNING: The type SearchSemantics (a.k.a. !search-semantics) is deprecated and will be removed.\n         Have a look at CompositeQuery (a.k.a. !composite-query) instead.");
      normalizeOutput = function(output) {
        if (typeof output === "object" && Object.keys(output).length === 1 && (output.query != null)) {
          issueWarning("WARNING: One of your query components outputs an extranous `query`-prefix.\n         This is not necessary anymore and will constitute an error in\n         future releases.");
          output = output.query;
        }
        return output;
      };
      return this.apply = function(req, settings, attributes) {
        var defaultQueryComponents, identity, initialQuery, initialQuery0, postprocess, query, queryComponents, r, reducer, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, type, typeName;
        ({
          query,
          type: typeName
        } = req);
        defaultQueryComponents = [new MultiMatchQuery(), new FilterQuery()];
        type = settings != null ? settings.types[typeName] : void 0;
        identity = function(x) {
          return x;
        };
        postprocess = (ref = (ref1 = this._options) != null ? ref1.postprocess : void 0) != null ? ref : function(o) {
          if (Object.keys(o).length === 0) {
            return {
              match_all: {}
            };
          } else {
            return o;
          }
        };
        queryComponents = (ref2 = (ref3 = this._options) != null ? ref3.queryComponents : void 0) != null ? ref2 : defaultQueryComponents;
        reducer = (ref4 = (ref5 = this._options) != null ? ref5.reducer : void 0) != null ? ref4 : function(a, b) {
          return merge(a, b);
        };
        initialQuery0 = (ref6 = (ref7 = this._options) != null ? ref7.initialQuery : void 0) != null ? ref6 : {};
        initialQuery = (typeof initialQuery0 === 'function' ? initialQuery0(query, type) : initialQuery0);
        r = queryComponents.map(function(qc) {
          var output;
          output = qc.create(query, type, attributes);
          return normalizeOutput(output);
        }).reduce(reducer, initialQuery);
        return call(postprocess)(r);
      };
    }

  };

}).call(this);
