/*
 * Copyright Elasticsearch B.V. and contributors
 * SPDX-License-Identifier: Apache-2.0
 */

// This file was automatically generated by elastic/elastic-client-generator-js
// DO NOT MODIFY IT BY HAND. Instead, modify the source open api file,
// and elastic/elastic-client-generator-js to regenerate this file again.

import {
  Transport,
  TransportRequestMetadata,
  TransportRequestOptions,
  TransportRequestOptionsWithMeta,
  TransportRequestOptionsWithOutMeta,
  TransportResult
} from '@elastic/transport'
import * as T from '../types'
import { kAcceptedParams } from '../../symbols'

interface That {
  transport: Transport
  [kAcceptedParams]: Record<string, { path: string[], body: string[], query: string[] }>
}

const commonQueryParams = ['error_trace', 'filter_path', 'human', 'pretty']

export default class Nodes {
  transport: Transport
  [kAcceptedParams]: Record<string, { path: string[], body: string[], query: string[] }>
  constructor (transport: Transport) {
    this.transport = transport
    this[kAcceptedParams] = {
      'nodes.clear_repositories_metering_archive': {
        path: [
          'node_id',
          'max_archive_version'
        ],
        body: [],
        query: []
      },
      'nodes.get_repositories_metering_info': {
        path: [
          'node_id'
        ],
        body: [],
        query: []
      },
      'nodes.hot_threads': {
        path: [
          'node_id'
        ],
        body: [],
        query: [
          'ignore_idle_threads',
          'interval',
          'snapshots',
          'threads',
          'timeout',
          'type',
          'sort'
        ]
      },
      'nodes.info': {
        path: [
          'node_id',
          'metric'
        ],
        body: [],
        query: [
          'flat_settings',
          'timeout'
        ]
      },
      'nodes.reload_secure_settings': {
        path: [
          'node_id'
        ],
        body: [
          'secure_settings_password'
        ],
        query: [
          'timeout'
        ]
      },
      'nodes.stats': {
        path: [
          'node_id',
          'metric',
          'index_metric'
        ],
        body: [],
        query: [
          'completion_fields',
          'fielddata_fields',
          'fields',
          'groups',
          'include_segment_file_sizes',
          'level',
          'timeout',
          'types',
          'include_unloaded_segments'
        ]
      },
      'nodes.usage': {
        path: [
          'node_id',
          'metric'
        ],
        body: [],
        query: [
          'timeout'
        ]
      }
    }
  }

  /**
    * Clear the archived repositories metering. Clear the archived repositories metering information in the cluster.
    * @see {@link https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-nodes-clear-repositories-metering-archive | Elasticsearch API documentation}
    */
  async clearRepositoriesMeteringArchive (this: That, params: T.NodesClearRepositoriesMeteringArchiveRequest, options?: TransportRequestOptionsWithOutMeta): Promise<T.NodesClearRepositoriesMeteringArchiveResponse>
  async clearRepositoriesMeteringArchive (this: That, params: T.NodesClearRepositoriesMeteringArchiveRequest, options?: TransportRequestOptionsWithMeta): Promise<TransportResult<T.NodesClearRepositoriesMeteringArchiveResponse, unknown>>
  async clearRepositoriesMeteringArchive (this: That, params: T.NodesClearRepositoriesMeteringArchiveRequest, options?: TransportRequestOptions): Promise<T.NodesClearRepositoriesMeteringArchiveResponse>
  async clearRepositoriesMeteringArchive (this: That, params: T.NodesClearRepositoriesMeteringArchiveRequest, options?: TransportRequestOptions): Promise<any> {
    const {
      path: acceptedPath
    } = this[kAcceptedParams]['nodes.clear_repositories_metering_archive']

    const userQuery = params?.querystring
    const querystring: Record<string, any> = userQuery != null ? { ...userQuery } : {}

    let body: Record<string, any> | string | undefined
    const userBody = params?.body
    if (userBody != null) {
      if (typeof userBody === 'string') {
        body = userBody
      } else {
        body = { ...userBody }
      }
    }

    for (const key in params) {
      if (acceptedPath.includes(key)) {
        continue
      } else if (key !== 'body' && key !== 'querystring') {
        // @ts-expect-error
        querystring[key] = params[key]
      }
    }

    const method = 'DELETE'
    const path = `/_nodes/${encodeURIComponent(params.node_id.toString())}/_repositories_metering/${encodeURIComponent(params.max_archive_version.toString())}`
    const meta: TransportRequestMetadata = {
      name: 'nodes.clear_repositories_metering_archive',
      pathParts: {
        node_id: params.node_id,
        max_archive_version: params.max_archive_version
      },
      acceptedParams: {
        path: ['node_id', 'max_archive_version'],
        body: [],
        query: []
      }
    }
    return await this.transport.request({ path, method, querystring, body, meta }, options)
  }

  /**
    * Get cluster repositories metering. Get repositories metering information for a cluster. This API exposes monotonically non-decreasing counters and it is expected that clients would durably store the information needed to compute aggregations over a period of time. Additionally, the information exposed by this API is volatile, meaning that it will not be present after node restarts.
    * @see {@link https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-nodes-get-repositories-metering-info | Elasticsearch API documentation}
    */
  async getRepositoriesMeteringInfo (this: That, params: T.NodesGetRepositoriesMeteringInfoRequest, options?: TransportRequestOptionsWithOutMeta): Promise<T.NodesGetRepositoriesMeteringInfoResponse>
  async getRepositoriesMeteringInfo (this: That, params: T.NodesGetRepositoriesMeteringInfoRequest, options?: TransportRequestOptionsWithMeta): Promise<TransportResult<T.NodesGetRepositoriesMeteringInfoResponse, unknown>>
  async getRepositoriesMeteringInfo (this: That, params: T.NodesGetRepositoriesMeteringInfoRequest, options?: TransportRequestOptions): Promise<T.NodesGetRepositoriesMeteringInfoResponse>
  async getRepositoriesMeteringInfo (this: That, params: T.NodesGetRepositoriesMeteringInfoRequest, options?: TransportRequestOptions): Promise<any> {
    const {
      path: acceptedPath
    } = this[kAcceptedParams]['nodes.get_repositories_metering_info']

    const userQuery = params?.querystring
    const querystring: Record<string, any> = userQuery != null ? { ...userQuery } : {}

    let body: Record<string, any> | string | undefined
    const userBody = params?.body
    if (userBody != null) {
      if (typeof userBody === 'string') {
        body = userBody
      } else {
        body = { ...userBody }
      }
    }

    for (const key in params) {
      if (acceptedPath.includes(key)) {
        continue
      } else if (key !== 'body' && key !== 'querystring') {
        // @ts-expect-error
        querystring[key] = params[key]
      }
    }

    const method = 'GET'
    const path = `/_nodes/${encodeURIComponent(params.node_id.toString())}/_repositories_metering`
    const meta: TransportRequestMetadata = {
      name: 'nodes.get_repositories_metering_info',
      pathParts: {
        node_id: params.node_id
      },
      acceptedParams: {
        path: ['node_id'],
        body: [],
        query: []
      }
    }
    return await this.transport.request({ path, method, querystring, body, meta }, options)
  }

  /**
    * Get the hot threads for nodes. Get a breakdown of the hot threads on each selected node in the cluster. The output is plain text with a breakdown of the top hot threads for each node.
    * @see {@link https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-nodes-hot-threads | Elasticsearch API documentation}
    */
  async hotThreads (this: That, params?: T.NodesHotThreadsRequest, options?: TransportRequestOptionsWithOutMeta): Promise<T.NodesHotThreadsResponse>
  async hotThreads (this: That, params?: T.NodesHotThreadsRequest, options?: TransportRequestOptionsWithMeta): Promise<TransportResult<T.NodesHotThreadsResponse, unknown>>
  async hotThreads (this: That, params?: T.NodesHotThreadsRequest, options?: TransportRequestOptions): Promise<T.NodesHotThreadsResponse>
  async hotThreads (this: That, params?: T.NodesHotThreadsRequest, options?: TransportRequestOptions): Promise<any> {
    const {
      path: acceptedPath
    } = this[kAcceptedParams]['nodes.hot_threads']

    const userQuery = params?.querystring
    const querystring: Record<string, any> = userQuery != null ? { ...userQuery } : {}

    let body: Record<string, any> | string | undefined
    const userBody = params?.body
    if (userBody != null) {
      if (typeof userBody === 'string') {
        body = userBody
      } else {
        body = { ...userBody }
      }
    }

    params = params ?? {}
    for (const key in params) {
      if (acceptedPath.includes(key)) {
        continue
      } else if (key !== 'body' && key !== 'querystring') {
        // @ts-expect-error
        querystring[key] = params[key]
      }
    }

    let method = ''
    let path = ''
    if (params.node_id != null) {
      method = 'GET'
      path = `/_nodes/${encodeURIComponent(params.node_id.toString())}/hot_threads`
    } else {
      method = 'GET'
      path = '/_nodes/hot_threads'
    }
    const meta: TransportRequestMetadata = {
      name: 'nodes.hot_threads',
      pathParts: {
        node_id: params.node_id
      },
      acceptedParams: {
        path: ['node_id'],
        body: [],
        query: ['ignore_idle_threads', 'interval', 'snapshots', 'threads', 'timeout', 'type', 'sort']
      }
    }
    return await this.transport.request({ path, method, querystring, body, meta }, options)
  }

  /**
    * Get node information. By default, the API returns all attributes and core settings for cluster nodes.
    * @see {@link https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-nodes-info | Elasticsearch API documentation}
    */
  async info (this: That, params?: T.NodesInfoRequest, options?: TransportRequestOptionsWithOutMeta): Promise<T.NodesInfoResponse>
  async info (this: That, params?: T.NodesInfoRequest, options?: TransportRequestOptionsWithMeta): Promise<TransportResult<T.NodesInfoResponse, unknown>>
  async info (this: That, params?: T.NodesInfoRequest, options?: TransportRequestOptions): Promise<T.NodesInfoResponse>
  async info (this: That, params?: T.NodesInfoRequest, options?: TransportRequestOptions): Promise<any> {
    const {
      path: acceptedPath
    } = this[kAcceptedParams]['nodes.info']

    const userQuery = params?.querystring
    const querystring: Record<string, any> = userQuery != null ? { ...userQuery } : {}

    let body: Record<string, any> | string | undefined
    const userBody = params?.body
    if (userBody != null) {
      if (typeof userBody === 'string') {
        body = userBody
      } else {
        body = { ...userBody }
      }
    }

    params = params ?? {}
    for (const key in params) {
      if (acceptedPath.includes(key)) {
        continue
      } else if (key !== 'body' && key !== 'querystring') {
        // @ts-expect-error
        querystring[key] = params[key]
      }
    }

    let method = ''
    let path = ''
    if (params.node_id != null && params.metric != null) {
      method = 'GET'
      path = `/_nodes/${encodeURIComponent(params.node_id.toString())}/${encodeURIComponent(params.metric.toString())}`
    } else if (params.node_id != null) {
      method = 'GET'
      path = `/_nodes/${encodeURIComponent(params.node_id.toString())}`
    } else if (params.metric != null) {
      method = 'GET'
      path = `/_nodes/${encodeURIComponent(params.metric.toString())}`
    } else {
      method = 'GET'
      path = '/_nodes'
    }
    const meta: TransportRequestMetadata = {
      name: 'nodes.info',
      pathParts: {
        node_id: params.node_id,
        metric: params.metric
      },
      acceptedParams: {
        path: ['node_id', 'metric'],
        body: [],
        query: ['flat_settings', 'timeout']
      }
    }
    return await this.transport.request({ path, method, querystring, body, meta }, options)
  }

  /**
    * Reload the keystore on nodes in the cluster. Secure settings are stored in an on-disk keystore. Certain of these settings are reloadable. That is, you can change them on disk and reload them without restarting any nodes in the cluster. When you have updated reloadable secure settings in your keystore, you can use this API to reload those settings on each node. When the Elasticsearch keystore is password protected and not simply obfuscated, you must provide the password for the keystore when you reload the secure settings. Reloading the settings for the whole cluster assumes that the keystores for all nodes are protected with the same password; this method is allowed only when inter-node communications are encrypted. Alternatively, you can reload the secure settings on each node by locally accessing the API and passing the node-specific Elasticsearch keystore password.
    * @see {@link https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-nodes-reload-secure-settings | Elasticsearch API documentation}
    */
  async reloadSecureSettings (this: That, params?: T.NodesReloadSecureSettingsRequest, options?: TransportRequestOptionsWithOutMeta): Promise<T.NodesReloadSecureSettingsResponse>
  async reloadSecureSettings (this: That, params?: T.NodesReloadSecureSettingsRequest, options?: TransportRequestOptionsWithMeta): Promise<TransportResult<T.NodesReloadSecureSettingsResponse, unknown>>
  async reloadSecureSettings (this: That, params?: T.NodesReloadSecureSettingsRequest, options?: TransportRequestOptions): Promise<T.NodesReloadSecureSettingsResponse>
  async reloadSecureSettings (this: That, params?: T.NodesReloadSecureSettingsRequest, options?: TransportRequestOptions): Promise<any> {
    const {
      path: acceptedPath,
      body: acceptedBody,
      query: acceptedQuery
    } = this[kAcceptedParams]['nodes.reload_secure_settings']

    const userQuery = params?.querystring
    const querystring: Record<string, any> = userQuery != null ? { ...userQuery } : {}

    let body: Record<string, any> | string | undefined
    const userBody = params?.body
    if (userBody != null) {
      if (typeof userBody === 'string') {
        body = userBody
      } else {
        body = { ...userBody }
      }
    }

    params = params ?? {}
    for (const key in params) {
      if (acceptedBody.includes(key)) {
        body = body ?? {}
        // @ts-expect-error
        body[key] = params[key]
      } else if (acceptedPath.includes(key)) {
        continue
      } else if (key !== 'body' && key !== 'querystring') {
        if (acceptedQuery.includes(key) || commonQueryParams.includes(key)) {
          // @ts-expect-error
          querystring[key] = params[key]
        } else {
          body = body ?? {}
          // @ts-expect-error
          body[key] = params[key]
        }
      }
    }

    let method = ''
    let path = ''
    if (params.node_id != null) {
      method = 'POST'
      path = `/_nodes/${encodeURIComponent(params.node_id.toString())}/reload_secure_settings`
    } else {
      method = 'POST'
      path = '/_nodes/reload_secure_settings'
    }
    const meta: TransportRequestMetadata = {
      name: 'nodes.reload_secure_settings',
      pathParts: {
        node_id: params.node_id
      },
      acceptedParams: {
        path: ['node_id'],
        body: ['secure_settings_password'],
        query: ['timeout']
      }
    }
    return await this.transport.request({ path, method, querystring, body, meta }, options)
  }

  /**
    * Get node statistics. Get statistics for nodes in a cluster. By default, all stats are returned. You can limit the returned information by using metrics.
    * @see {@link https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-nodes-stats | Elasticsearch API documentation}
    */
  async stats (this: That, params?: T.NodesStatsRequest, options?: TransportRequestOptionsWithOutMeta): Promise<T.NodesStatsResponse>
  async stats (this: That, params?: T.NodesStatsRequest, options?: TransportRequestOptionsWithMeta): Promise<TransportResult<T.NodesStatsResponse, unknown>>
  async stats (this: That, params?: T.NodesStatsRequest, options?: TransportRequestOptions): Promise<T.NodesStatsResponse>
  async stats (this: That, params?: T.NodesStatsRequest, options?: TransportRequestOptions): Promise<any> {
    const {
      path: acceptedPath
    } = this[kAcceptedParams]['nodes.stats']

    const userQuery = params?.querystring
    const querystring: Record<string, any> = userQuery != null ? { ...userQuery } : {}

    let body: Record<string, any> | string | undefined
    const userBody = params?.body
    if (userBody != null) {
      if (typeof userBody === 'string') {
        body = userBody
      } else {
        body = { ...userBody }
      }
    }

    params = params ?? {}
    for (const key in params) {
      if (acceptedPath.includes(key)) {
        continue
      } else if (key !== 'body' && key !== 'querystring') {
        // @ts-expect-error
        querystring[key] = params[key]
      }
    }

    let method = ''
    let path = ''
    if (params.node_id != null && params.metric != null && params.index_metric != null) {
      method = 'GET'
      path = `/_nodes/${encodeURIComponent(params.node_id.toString())}/stats/${encodeURIComponent(params.metric.toString())}/${encodeURIComponent(params.index_metric.toString())}`
    } else if (params.node_id != null && params.metric != null) {
      method = 'GET'
      path = `/_nodes/${encodeURIComponent(params.node_id.toString())}/stats/${encodeURIComponent(params.metric.toString())}`
    } else if (params.metric != null && params.index_metric != null) {
      method = 'GET'
      path = `/_nodes/stats/${encodeURIComponent(params.metric.toString())}/${encodeURIComponent(params.index_metric.toString())}`
    } else if (params.node_id != null) {
      method = 'GET'
      path = `/_nodes/${encodeURIComponent(params.node_id.toString())}/stats`
    } else if (params.metric != null) {
      method = 'GET'
      path = `/_nodes/stats/${encodeURIComponent(params.metric.toString())}`
    } else {
      method = 'GET'
      path = '/_nodes/stats'
    }
    const meta: TransportRequestMetadata = {
      name: 'nodes.stats',
      pathParts: {
        node_id: params.node_id,
        metric: params.metric,
        index_metric: params.index_metric
      },
      acceptedParams: {
        path: ['node_id', 'metric', 'index_metric'],
        body: [],
        query: ['completion_fields', 'fielddata_fields', 'fields', 'groups', 'include_segment_file_sizes', 'level', 'timeout', 'types', 'include_unloaded_segments']
      }
    }
    return await this.transport.request({ path, method, querystring, body, meta }, options)
  }

  /**
    * Get feature usage information.
    * @see {@link https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-nodes-usage | Elasticsearch API documentation}
    */
  async usage (this: That, params?: T.NodesUsageRequest, options?: TransportRequestOptionsWithOutMeta): Promise<T.NodesUsageResponse>
  async usage (this: That, params?: T.NodesUsageRequest, options?: TransportRequestOptionsWithMeta): Promise<TransportResult<T.NodesUsageResponse, unknown>>
  async usage (this: That, params?: T.NodesUsageRequest, options?: TransportRequestOptions): Promise<T.NodesUsageResponse>
  async usage (this: That, params?: T.NodesUsageRequest, options?: TransportRequestOptions): Promise<any> {
    const {
      path: acceptedPath
    } = this[kAcceptedParams]['nodes.usage']

    const userQuery = params?.querystring
    const querystring: Record<string, any> = userQuery != null ? { ...userQuery } : {}

    let body: Record<string, any> | string | undefined
    const userBody = params?.body
    if (userBody != null) {
      if (typeof userBody === 'string') {
        body = userBody
      } else {
        body = { ...userBody }
      }
    }

    params = params ?? {}
    for (const key in params) {
      if (acceptedPath.includes(key)) {
        continue
      } else if (key !== 'body' && key !== 'querystring') {
        // @ts-expect-error
        querystring[key] = params[key]
      }
    }

    let method = ''
    let path = ''
    if (params.node_id != null && params.metric != null) {
      method = 'GET'
      path = `/_nodes/${encodeURIComponent(params.node_id.toString())}/usage/${encodeURIComponent(params.metric.toString())}`
    } else if (params.node_id != null) {
      method = 'GET'
      path = `/_nodes/${encodeURIComponent(params.node_id.toString())}/usage`
    } else if (params.metric != null) {
      method = 'GET'
      path = `/_nodes/usage/${encodeURIComponent(params.metric.toString())}`
    } else {
      method = 'GET'
      path = '/_nodes/usage'
    }
    const meta: TransportRequestMetadata = {
      name: 'nodes.usage',
      pathParts: {
        node_id: params.node_id,
        metric: params.metric
      },
      acceptedParams: {
        path: ['node_id', 'metric'],
        body: [],
        query: ['timeout']
      }
    }
    return await this.transport.request({ path, method, querystring, body, meta }, options)
  }
}
