// SPDX-FileCopyrightText: Copyright (c) Kitware Inc.
// SPDX-FileCopyrightText: Copyright (c) Sandia Corporation
// SPDX-License-Identifier: BSD-3-Clause

#ifndef pqServerResource_h
#define pqServerResource_h

#include "pqCoreModule.h"

#include "vtkParaViewDeprecation.h" // for PARAVIEW_DEPRECATED_IN_5_11_0

#include <QString>
class pqServerConfiguration;

/**
 * pqServerResource encapsulates a resource in ParaView. A resource can be anything,
 * a data file, a list of data files, a state file, or a connection to a server.
 * The resource specification is based on URL-like syntax:
 * \verbatim
 * <scheme>://<scheme-specific-parameters>
 * \endverbatim
 *
 * To specify a data or state file, the following syntax is used:
 * \verbatim
 * <connection-scheme>:[//<server-details>]/<path-to-data-file>[#serverName]:KEY:1
 * \endverbatim
 *
 * \c connection-scheme can be
 * \li \c builtin - for builtin connections
 * \li \c cs - for client-server connections (pvserver)
 * \li \c csrc - for client-server connections with reverse-connect (pvserver rc)
 * \li \c cdsrs - for client-data-server-render-server connections (pvdataserver, pvrenderserver)
 * \li \c cdsrsrc - for cdsrs with reverse-connect.
 *
 * \c server-details are of the form \c \<serverhost-name\>:\<port\> or
 * \c \<dataserver-hostname\>:\<dataserver-port\>/\<renderserver-hostname\>:\<render-server-port\>
 * as applicable. Port numbers are always optional.
 *
 * The KEY should be PARAVIEW_DATA for data file and PARAVIEW_STATE for state file.
 *
 * Examples:
 * \verbatim
 * builtin:/home/user/foo.vtk
 * cs://amber1:11112/C:\Users\User\foo.vtk
 * cdsrsrc://amber2:11111/amber3:22222/home/user/foo.vtk#amberDRS
 * \endverbatim
 *
 * To specify a server-connection, without pointing to any data file(s), the
 * following syntax may be used:
 * \verbatim
 * <connection-scheme>:[//<server-details>]
 * \endverbatim
 *
 * Examples:
 * \verbatim
 * builtin:
 * cs://amber1:11112
 * cdsrsrc://amber2:11111/amber3:22222
 * \endverbatim
 *
 * As with data-files, port numbers are always optional in when specifying
 * server-details.
 *
 * Server name is also optional but will be used if available.
 *
 * Arbitrary data can be added to a resource. ParaView leverages this mechanism
 * to identify statefiles, to save additional files in a file series
 * when referring to a data file, or details about how to connect to the server
 * when referring to a server-connection.
 *
 * \sa pqServerResources, pqServer
 */
class PQCORE_EXPORT pqServerResource
{
public:
  pqServerResource();
  ~pqServerResource();
  pqServerResource& operator=(const pqServerResource&);

  /**
   * Create an pqServerResource from a provided URI
   */
  pqServerResource(const QString& uri);

  /**
   * Create an pqServerResource from a provided URI and store related configuration
   * If the configuration is named, the configuration name will be used as a serverName
   */
  pqServerResource(const QString& uri, const pqServerConfiguration& config);

  /**
   * Create a pqServerResource by copy
   */
  pqServerResource(const pqServerResource&);

  /**
   * Returns the pqServerConfiguration from which this resource was created, if any.
   */
  const pqServerConfiguration& configuration() const;

  /**
   * Returns a compact string representation of the complete resource in URI format, see above.
   */
  QString toURI() const;

  /**
   * Returns a compact string representation of the resource including extra data
   */
  QString serializeString() const;

  /**
   * Returns the resource scheme, builtin, cs, csrc, cdsrs or cdsrsrc
   */
  QString scheme() const;

  /**
   * Sets the resource scheme
   */
  void setScheme(const QString&);

  /**
   * Returns if the connection scheme is a reverse one
   */
  bool isReverse() const;

  /**
   * Returns the resource host, or empty string for builtin, cdsrs, and cdsrsrc schemes
   */
  QString host() const;

  /**
   * Sets the resource host
   */
  void setHost(const QString&);

  /**
   * Return the resource port, or -1 for builtin, cdsrs, and cdsrsrc schemes
   */
  int port() const;

  /**
   * Return the resource port, or default_port for builtin, cdsrs, and cdsrsrc schemes
   */
  int port(int default_port) const;

  /**
   * Set the resource port
   */
  void setPort(int);

  /**
   * Return the data server host, if any
   */
  QString dataServerHost() const;

  /**
   * Set the data server host
   */
  void setDataServerHost(const QString&);

  /**
   * Return the data server port, if any, or -1
   */
  int dataServerPort() const;

  /**
   * Return the data server port, if any, or default_port
   */
  int dataServerPort(int default_port) const;

  /**
   * Set the data server port
   */
  void setDataServerPort(int);

  /**
   * Return the render server host, if any
   */
  QString renderServerHost() const;

  /**
   * Set the render server host
   */
  void setRenderServerHost(const QString&);

  /**
   * Return the render server port, if any, or -1
   */
  int renderServerPort() const;

  /**
   * Return the render server port, if any, or default_port
   */
  int renderServerPort(int default_port) const;

  /**
   * Set the render server port
   */
  void setRenderServerPort(int);

  /**
   * Return the path to the resource, if any
   */
  QString path() const;

  /**
   * Set the path to the resource
   */
  void setPath(const QString&);

  /**
   * Return the server name of the resource, if any
   */
  QString serverName() const;

  /**
   * Set the server name of the resource
   */
  void setServerName(const QString& name);

  /**
   * Add a data on this resource, with a key/value logic
   */
  void addData(const QString& key, const QString& value);

  /**
   * Get data from this resource, associated with the provided key, if any
   */
  QString data(const QString& key) const;

  /**
   * Get data from this resource, associated with the provided key, if any. If not, return
   * default_value.
   */
  QString data(const QString& key, const QString& default_value) const;

  /**
   * Return true if this resource has data associated with the provided key, false otherwise.
   */
  bool hasData(const QString& key) const;

  /**
   * Returns a copy of this resource containing only server connection information -
   * scheme, host, and port numbers
   */
  pqServerResource schemeHostsPorts() const;

  /**
   * Returns a copy of this resource containing a subset of server information -
   * scheme and host (no port numbers)
   */
  pqServerResource schemeHosts() const;

  /**
   * Returns a copy of this resource containing only host and path information -
   * scheme and port numbers are excluded
   */
  pqServerResource hostPath() const;

  /**
   * Returns a copy of this resource containing only path and server name information -
   * scheme, host and port numbers are excluded
   */
  pqServerResource pathServerName() const;

  /**
   * Deprecated method, just return a copy of this
   */
  PARAVIEW_DEPRECATED_IN_5_11_0("Use the resource directly instead")
  pqServerResource sessionServer() const { return *this; };

  /**
   * Deprecated method, noop
   */
  PARAVIEW_DEPRECATED_IN_5_11_0("Use the resource directly instead")
  void setSessionServer(const pqServerResource&){};

  ///@{
  /**
   * Operators comparing all elements of the resource
   */
  bool operator==(const pqServerResource&) const;
  bool operator!=(const pqServerResource&) const;
  bool operator<(const pqServerResource&) const;
  ///@}

private:
  class pqImplementation;
  pqImplementation* const Implementation;
};

#endif
