"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.createMergedEsQuery = createMergedEsQuery;
exports.getEsQueryFromSavedSearch = getEsQueryFromSavedSearch;
exports.getQueryFromSavedSearchObject = getQueryFromSavedSearchObject;
exports.isSavedSearchSavedObject = isSavedSearchSavedObject;
var _lodash = require("lodash");
var _common = require("@kbn/data-plugin/common");
var _public = require("@kbn/data-plugin/public");
var _esQuery = require("@kbn/es-query");
var _mlIsPopulatedObject = require("@kbn/ml-is-populated-object");
var _mlQueryUtils = require("@kbn/ml-query-utils");
/*
 * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
 * or more contributor license agreements. Licensed under the Elastic License
 * 2.0; you may not use this file except in compliance with the Elastic License
 * 2.0.
 */

// TODO Consolidate with duplicate saved search utils file in
// `x-pack/plugins/data_visualizer/public/application/index_data_visualizer/utils/saved_search_utils.ts`

function isSavedSearchSavedObject(arg) {
  return (0, _mlIsPopulatedObject.isPopulatedObject)(arg, ['id', 'type', 'attributes']);
}

/**
 * Parse the stringified searchSourceJSON
 * from a saved search or saved search object
 */
function getQueryFromSavedSearchObject(savedSearch) {
  var _savedSearch$attribut;
  const search = isSavedSearchSavedObject(savedSearch) ? savedSearch === null || savedSearch === void 0 ? void 0 : (_savedSearch$attribut = savedSearch.attributes) === null || _savedSearch$attribut === void 0 ? void 0 : _savedSearch$attribut.kibanaSavedObjectMeta : // @ts-ignore
  savedSearch === null || savedSearch === void 0 ? void 0 : savedSearch.kibanaSavedObjectMeta;
  const parsed = typeof (search === null || search === void 0 ? void 0 : search.searchSourceJSON) === 'string' ? JSON.parse(search.searchSourceJSON) : undefined;

  // Remove indexRefName because saved search might no longer be relevant
  // if user modifies the query or filter
  // after opening a saved search
  if (parsed && Array.isArray(parsed.filter)) {
    parsed.filter.forEach(f => {
      // @ts-expect-error indexRefName does appear in meta for newly created saved search
      f.meta.indexRefName = undefined;
    });
  }
  return parsed;
}

/**
 * Create an Elasticsearch query that combines both lucene/kql query string and filters
 * Should also form a valid query if only the query or filters is provided
 */
function createMergedEsQuery(query, filters, dataView, uiSettings) {
  let combinedQuery = (0, _mlQueryUtils.getDefaultDSLQuery)();

  // FIXME: Add support for AggregateQuery type #150091
  if ((0, _public.isQuery)(query) && query.language === _mlQueryUtils.SEARCH_QUERY_LANGUAGE.KUERY) {
    const ast = (0, _esQuery.fromKueryExpression)(query.query);
    if (query.query !== '') {
      combinedQuery = (0, _esQuery.toElasticsearchQuery)(ast, dataView);
    }
    if (combinedQuery.bool !== undefined) {
      const filterQuery = (0, _esQuery.buildQueryFromFilters)(filters, dataView);
      if (!Array.isArray(combinedQuery.bool.filter)) {
        combinedQuery.bool.filter = combinedQuery.bool.filter === undefined ? [] : [combinedQuery.bool.filter];
      }
      if (!Array.isArray(combinedQuery.bool.must_not)) {
        combinedQuery.bool.must_not = combinedQuery.bool.must_not === undefined ? [] : [combinedQuery.bool.must_not];
      }
      combinedQuery.bool.filter = [...combinedQuery.bool.filter, ...filterQuery.filter];
      combinedQuery.bool.must_not = [...combinedQuery.bool.must_not, ...filterQuery.must_not];
    }
  } else {
    combinedQuery = (0, _esQuery.buildEsQuery)(dataView, query ? [query] : [], filters ? filters : [], uiSettings ? (0, _common.getEsQueryConfig)(uiSettings) : undefined);
  }
  return combinedQuery;
}
function getSavedSearchSource(savedSearch) {
  return savedSearch && 'searchSource' in savedSearch && (savedSearch === null || savedSearch === void 0 ? void 0 : savedSearch.searchSource) instanceof _common.SearchSource ? savedSearch.searchSource : undefined;
}

/**
 * Extract query data from the saved search object
 * with overrides from the provided query data and/or filters
 */
function getEsQueryFromSavedSearch({
  dataView,
  uiSettings,
  savedSearch,
  query,
  filters,
  filterManager
}) {
  if (!dataView || !savedSearch) return;
  const userQuery = query;
  const userFilters = filters;
  const savedSearchSource = getSavedSearchSource(savedSearch);

  // If saved search has a search source with nested parent
  // e.g. a search coming from Dashboard saved search embeddable
  // which already combines both the saved search's original query/filters and the Dashboard's
  // then no need to process any further
  if (savedSearchSource && savedSearchSource.getParent() !== undefined && userQuery) {
    var _cloneDeep, _savedSearch$searchSo, _savedSearch$searchSo2;
    // Flattened query from search source may contain a clause that narrows the time range
    // which might interfere with global time pickers so we need to remove
    const savedQuery = (_cloneDeep = (0, _lodash.cloneDeep)((_savedSearch$searchSo = savedSearch.searchSource.getSearchRequestBody()) === null || _savedSearch$searchSo === void 0 ? void 0 : _savedSearch$searchSo.query)) !== null && _cloneDeep !== void 0 ? _cloneDeep : (0, _mlQueryUtils.getDefaultDSLQuery)();
    const timeField = (_savedSearch$searchSo2 = savedSearch.searchSource.getField('index')) === null || _savedSearch$searchSo2 === void 0 ? void 0 : _savedSearch$searchSo2.timeFieldName;
    if (Array.isArray(savedQuery.bool.filter) && timeField !== undefined) {
      savedQuery.bool.filter = savedQuery.bool.filter.filter(c => {
        var _c$range;
        return !(c.hasOwnProperty('range') && (_c$range = c.range) !== null && _c$range !== void 0 && _c$range.hasOwnProperty(timeField));
      });
    }
    return {
      searchQuery: savedQuery,
      searchString: userQuery.query,
      queryLanguage: userQuery.language
    };
  }

  // If no saved search available, use user's query and filters
  if (!savedSearch && userQuery) {
    if (filterManager && userFilters) filterManager.addFilters(userFilters);
    const combinedQuery = createMergedEsQuery(userQuery, Array.isArray(userFilters) ? userFilters : [], dataView, uiSettings);
    return {
      searchQuery: combinedQuery,
      searchString: userQuery.query,
      queryLanguage: userQuery.language
    };
  }

  // If saved search available, merge saved search with the latest user query or filters
  // which might differ from extracted saved search data
  if (savedSearchSource) {
    const globalFilters = filterManager === null || filterManager === void 0 ? void 0 : filterManager.getGlobalFilters();
    // FIXME: Add support for AggregateQuery type #150091
    const currentQuery = userQuery !== null && userQuery !== void 0 ? userQuery : savedSearchSource.getField('query');
    const currentFilters = userFilters !== null && userFilters !== void 0 ? userFilters : (0, _public.mapAndFlattenFilters)(savedSearchSource.getField('filter'));
    if (filterManager) filterManager.setFilters(currentFilters);
    if (globalFilters) filterManager === null || filterManager === void 0 ? void 0 : filterManager.addFilters(globalFilters);
    const combinedQuery = createMergedEsQuery(currentQuery, filterManager ? filterManager === null || filterManager === void 0 ? void 0 : filterManager.getFilters() : currentFilters, dataView, uiSettings);
    return {
      searchQuery: combinedQuery,
      searchString: currentQuery.query,
      queryLanguage: currentQuery.language
    };
  }
}