"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.syncUnifiedSearchState = syncUnifiedSearchState;
var _rxjs = require("rxjs");
var _fastDeepEqual = _interopRequireDefault(require("fast-deep-equal"));
var _operators = require("rxjs/operators");
var _public = require("@kbn/presentation-util-plugin/public");
var _public2 = require("@kbn/data-plugin/public");
var _plugin_services = require("../../../../services/plugin_services");
var _dashboard_constants = require("../../../../dashboard_constants");
var _dashboard_diffing_utils = require("../../../state/diffing/dashboard_diffing_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 and the Server Side Public License, v 1; you may not use this file except
 * in compliance with, at your election, the Elastic License 2.0 or the Server
 * Side Public License, v 1.
 */

/**
 * Sets up syncing and subscriptions between the filter state from the Data plugin
 * and the dashboard Redux store.
 */
function syncUnifiedSearchState(kbnUrlStateStorage) {
  const {
    data: {
      query: queryService,
      search
    }
  } = _plugin_services.pluginServices.getServices();
  const {
    queryString,
    timefilter
  } = queryService;
  const {
    timefilter: timefilterService
  } = timefilter;

  // get Observable for when the dashboard's saved filters or query change.
  const OnFiltersChange$ = new _rxjs.Subject();
  const unsubscribeFromSavedFilterChanges = this.onStateChange(() => {
    const {
      explicitInput: {
        filters,
        query
      }
    } = this.getState();
    OnFiltersChange$.next({
      filters: filters !== null && filters !== void 0 ? filters : [],
      query: query !== null && query !== void 0 ? query : queryString.getDefaultQuery()
    });
  });

  // starts syncing app filters between dashboard state and filterManager
  const {
    explicitInput: {
      filters,
      query
    }
  } = this.getState();
  const intermediateFilterState = {
    query: query !== null && query !== void 0 ? query : queryString.getDefaultQuery(),
    filters: filters !== null && filters !== void 0 ? filters : []
  };
  const stopSyncingAppFilters = (0, _public2.connectToQueryState)(queryService, {
    get: () => intermediateFilterState,
    set: ({
      filters: newFilters,
      query: newQuery
    }) => {
      intermediateFilterState.filters = (0, _public.cleanFiltersForSerialize)(newFilters);
      intermediateFilterState.query = newQuery;
      this.dispatch.setFiltersAndQuery(intermediateFilterState);
    },
    state$: OnFiltersChange$.pipe((0, _operators.distinctUntilChanged)())
  }, {
    query: true,
    filters: true
  });
  const timeUpdateSubscription = timefilterService.getTimeUpdate$().subscribe(() => {
    const newTimeRange = (_kbnUrlStateStorage$g => {
      // if there is an override time range in the URL, use it.
      const urlOverrideTimeRange = (_kbnUrlStateStorage$g = kbnUrlStateStorage.get(_dashboard_constants.GLOBAL_STATE_STORAGE_KEY)) === null || _kbnUrlStateStorage$g === void 0 ? void 0 : _kbnUrlStateStorage$g.time;
      if (urlOverrideTimeRange) return urlOverrideTimeRange;

      // if there is no url override time range, check if this dashboard uses time restore, and restore to that.
      const timeRestoreTimeRange = this.getState().explicitInput.timeRestore && this.getState().componentState.lastSavedInput.timeRange;
      if (timeRestoreTimeRange) {
        timefilterService.setTime(timeRestoreTimeRange);
        return timeRestoreTimeRange;
      }

      // otherwise fall back to the time range from the time filter service
      return timefilterService.getTime();
    })();
    const lastTimeRange = this.getState().explicitInput.timeRange;
    if (!(0, _dashboard_diffing_utils.areTimesEqual)(newTimeRange.from, lastTimeRange === null || lastTimeRange === void 0 ? void 0 : lastTimeRange.from) || !(0, _dashboard_diffing_utils.areTimesEqual)(newTimeRange.to, lastTimeRange === null || lastTimeRange === void 0 ? void 0 : lastTimeRange.to)) {
      this.dispatch.setTimeRange(newTimeRange);
    }
  });
  const refreshIntervalSubscription = timefilterService.getRefreshIntervalUpdate$().subscribe(() => {
    const newRefreshInterval = (_kbnUrlStateStorage$g2 => {
      // if there is an override refresh interval in the URL, dispatch that to the dashboard.
      const urlOverrideRefreshInterval = (_kbnUrlStateStorage$g2 = kbnUrlStateStorage.get(_dashboard_constants.GLOBAL_STATE_STORAGE_KEY)) === null || _kbnUrlStateStorage$g2 === void 0 ? void 0 : _kbnUrlStateStorage$g2.refreshInterval;
      if (urlOverrideRefreshInterval) return urlOverrideRefreshInterval;

      // if there is no url override refresh interval, check if this dashboard uses time restore, and restore to that.
      const timeRestoreRefreshInterval = this.getState().explicitInput.timeRestore && this.getState().componentState.lastSavedInput.refreshInterval;
      if (timeRestoreRefreshInterval) {
        timefilterService.setRefreshInterval(timeRestoreRefreshInterval);
        return timeRestoreRefreshInterval;
      }

      // otherwise fall back to the refresh interval from the time filter service
      return timefilterService.getRefreshInterval();
    })();
    const lastRefreshInterval = this.getState().explicitInput.refreshInterval;
    if (!(0, _fastDeepEqual.default)(newRefreshInterval, lastRefreshInterval)) {
      this.dispatch.setRefreshInterval(newRefreshInterval);
    }
  });
  const autoRefreshSubscription = timefilterService.getAutoRefreshFetch$().pipe((0, _operators.tap)(() => {
    this.forceRefresh();
  }), (0, _operators.switchMap)(done =>
  // best way on a dashboard to estimate that panels are updated is to rely on search session service state
  (0, _public2.waitUntilNextSessionCompletes$)(search.session).pipe((0, _operators.finalize)(done)))).subscribe();
  const stopSyncingUnifiedSearchState = () => {
    autoRefreshSubscription.unsubscribe();
    timeUpdateSubscription.unsubscribe();
    refreshIntervalSubscription.unsubscribe();
    unsubscribeFromSavedFilterChanges();
    stopSyncingAppFilters();
  };
  return stopSyncingUnifiedSearchState;
}