/*
 * Copyright (C) 2020-2022 Open StApps
 * This program is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <https://www.gnu.org/licenses/>.
 */
import {SCThingsField} from '../../../meta.js';
import {SCSearchAbstractFilter, SCSearchAbstractFilterArguments} from '../filter.js';

/**
 * A date range filter
 *
 * Filter for documents with a date field that satisfies the given constraints
 * @see https://www.elastic.co/guide/en/elasticsearch/reference/5.6/query-dsl-range-query.html#_date_format_in_range_queries
 */
export interface SCSearchDateRangeFilter extends SCSearchAbstractFilter<SCDateRangeFilterArguments> {
  /**
   * @see SCSearchAbstractFilter.type
   */
  type: 'date range';
}

/**
 * A distance filter
 *
 * Filter for documents with a numeric field that satisfies the given constraints
 * @see https://www.elastic.co/guide/en/elasticsearch/reference/5.6/query-dsl-range-query.html#query-dsl-range-query
 */
export interface SCSearchNumericRangeFilter extends SCSearchAbstractFilter<SCNumericRangeFilterArguments> {
  /**
   * @see SCSearchAbstractFilter.type
   */
  type: 'numeric range';
}

/**
 * Additional arguments for date range filters
 *
 * Filter uses a plain string to allow for date math expressions
 * @see https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/date-math-expressions.html
 */
export interface SCDateRangeFilterArguments extends SCRangeFilterArguments<string> {
  /**
   * Optional date format specifier
   * @see https://www.elastic.co/guide/en/elasticsearch/reference/5.6/query-dsl-range-query.html#_date_format_in_range_queries
   */
  format?: string;

  /**
   * Optional timezone specifier
   * @see https://www.elastic.co/guide/en/elasticsearch/reference/5.6/query-dsl-range-query.html#_time_zone_in_range_queries
   */
  timeZone?: string;
}

/**
 * Additional arguments for numeric range filters
 */
export type SCNumericRangeFilterArguments = SCRangeFilterArguments<number>;

/**
 * Additional arguments for range filters
 * @see https://www.elastic.co/guide/en/elasticsearch/reference/5.6/query-dsl-range-query.html#query-dsl-range-query
 */
export interface SCRangeFilterArguments<T> extends SCSearchAbstractFilterArguments {
  /**
   * Bounds of the range
   */
  bounds: Bounds<T>;

  /**
   * Field where the filter will be applied
   */
  field: SCThingsField;

  /**
   * Relation when searching on other range fields
   *
   * Intersects (Default): Both search and field range intersect
   * Within: Search range is within the field range
   * Contains: Search range contains the field range
   */
  relation?: 'intersects' | 'within' | 'contains';
}

export interface Bounds<T> {
  /**
   * The lower bound
   */
  lowerBound?: Bound<T>;

  /**
   * The upper bound
   */
  upperBound?: Bound<T>;
}

export interface Bound<T> {
  /**
   * Limit of the bound
   */
  limit: T;

  /**
   * Bound mode
   */
  mode: 'inclusive' | 'exclusive';
}
