/**
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0.
 */

#pragma once
#include <aws/core/utils/memory/stl/AWSString.h>
#include <aws/core/utils/memory/stl/AWSVector.h>
#include <aws/sqs/SQSRequest.h>
#include <aws/sqs/SQS_EXPORTS.h>
#include <aws/sqs/model/MessageSystemAttributeName.h>

#include <utility>

namespace Aws {
namespace SQS {
namespace Model {

/**
 * <p>Retrieves one or more messages from a specified queue.</p><p><h3>See
 * Also:</h3>   <a
 * href="http://docs.aws.amazon.com/goto/WebAPI/sqs-2012-11-05/ReceiveMessageRequest">AWS
 * API Reference</a></p>
 */
class ReceiveMessageRequest : public SQSRequest {
 public:
  AWS_SQS_API ReceiveMessageRequest() = default;

  // Service request name is the Operation name which will send this request out,
  // each operation should has unique request name, so that we can get operation's name from this request.
  // Note: this is not true for response, multiple operations may have the same response name,
  // so we can not get operation's name from response.
  inline virtual const char* GetServiceRequestName() const override { return "ReceiveMessage"; }

  AWS_SQS_API Aws::String SerializePayload() const override;

  AWS_SQS_API Aws::Http::HeaderValueCollection GetRequestSpecificHeaders() const override;

  ///@{
  /**
   * <p>The URL of the Amazon SQS queue from which messages are received.</p>
   * <p>Queue URLs and names are case-sensitive.</p>
   */
  inline const Aws::String& GetQueueUrl() const { return m_queueUrl; }
  inline bool QueueUrlHasBeenSet() const { return m_queueUrlHasBeenSet; }
  template <typename QueueUrlT = Aws::String>
  void SetQueueUrl(QueueUrlT&& value) {
    m_queueUrlHasBeenSet = true;
    m_queueUrl = std::forward<QueueUrlT>(value);
  }
  template <typename QueueUrlT = Aws::String>
  ReceiveMessageRequest& WithQueueUrl(QueueUrlT&& value) {
    SetQueueUrl(std::forward<QueueUrlT>(value));
    return *this;
  }
  ///@}

  ///@{
  /**
   * <p>A list of attributes that need to be returned along with each message. These
   * attributes include:</p> <ul> <li> <p> <code>All</code> – Returns all values.</p>
   * </li> <li> <p> <code>ApproximateFirstReceiveTimestamp</code> – Returns the time
   * the message was first received from the queue (<a
   * href="http://en.wikipedia.org/wiki/Unix_time">epoch time</a> in
   * milliseconds).</p> </li> <li> <p> <code>ApproximateReceiveCount</code> – Returns
   * the number of times a message has been received across all queues but not
   * deleted.</p> </li> <li> <p> <code>AWSTraceHeader</code> – Returns the X-Ray
   * trace header string. </p> </li> <li> <p> <code>SenderId</code> </p> <ul> <li>
   * <p>For a user, returns the user ID, for example
   * <code>ABCDEFGHI1JKLMNOPQ23R</code>.</p> </li> <li> <p>For an IAM role, returns
   * the IAM role ID, for example <code>ABCDE1F2GH3I4JK5LMNOP:i-a123b456</code>.</p>
   * </li> </ul> </li> <li> <p> <code>SentTimestamp</code> – Returns the time the
   * message was sent to the queue (<a
   * href="http://en.wikipedia.org/wiki/Unix_time">epoch time</a> in
   * milliseconds).</p> </li> <li> <p> <code>SqsManagedSseEnabled</code> – Enables
   * server-side queue encryption using SQS owned encryption keys. Only one
   * server-side encryption option is supported per queue (for example, <a
   * href="https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-configure-sse-existing-queue.html">SSE-KMS</a>
   * or <a
   * href="https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-configure-sqs-sse-queue.html">SSE-SQS</a>).</p>
   * </li> <li> <p> <code>MessageDeduplicationId</code> – Returns the value provided
   * by the producer that calls the <code> <a>SendMessage</a> </code> action.</p>
   * </li> <li> <p> <code>MessageGroupId</code> – Returns the value provided by the
   * producer that calls the <code> <a>SendMessage</a> </code> action.</p> </li> <li>
   * <p> <code>SequenceNumber</code> – Returns the value provided by Amazon SQS.</p>
   * </li> </ul>
   */
  inline const Aws::Vector<MessageSystemAttributeName>& GetMessageSystemAttributeNames() const { return m_messageSystemAttributeNames; }
  inline bool MessageSystemAttributeNamesHasBeenSet() const { return m_messageSystemAttributeNamesHasBeenSet; }
  template <typename MessageSystemAttributeNamesT = Aws::Vector<MessageSystemAttributeName>>
  void SetMessageSystemAttributeNames(MessageSystemAttributeNamesT&& value) {
    m_messageSystemAttributeNamesHasBeenSet = true;
    m_messageSystemAttributeNames = std::forward<MessageSystemAttributeNamesT>(value);
  }
  template <typename MessageSystemAttributeNamesT = Aws::Vector<MessageSystemAttributeName>>
  ReceiveMessageRequest& WithMessageSystemAttributeNames(MessageSystemAttributeNamesT&& value) {
    SetMessageSystemAttributeNames(std::forward<MessageSystemAttributeNamesT>(value));
    return *this;
  }
  inline ReceiveMessageRequest& AddMessageSystemAttributeNames(MessageSystemAttributeName value) {
    m_messageSystemAttributeNamesHasBeenSet = true;
    m_messageSystemAttributeNames.push_back(value);
    return *this;
  }
  ///@}

  ///@{
  /**
   * <p>The name of the message attribute, where <i>N</i> is the index.</p> <ul> <li>
   * <p>The name can contain alphanumeric characters and the underscore
   * (<code>_</code>), hyphen (<code>-</code>), and period (<code>.</code>).</p>
   * </li> <li> <p>The name is case-sensitive and must be unique among all attribute
   * names for the message.</p> </li> <li> <p>The name must not start with
   * AWS-reserved prefixes such as <code>AWS.</code> or <code>Amazon.</code> (or any
   * casing variants).</p> </li> <li> <p>The name must not start or end with a period
   * (<code>.</code>), and it should not have periods in succession
   * (<code>..</code>).</p> </li> <li> <p>The name can be up to 256 characters
   * long.</p> </li> </ul> <p>When using <code>ReceiveMessage</code>, you can send a
   * list of attribute names to receive, or you can return all of the attributes by
   * specifying <code>All</code> or <code>.*</code> in your request. You can also use
   * all message attributes starting with a prefix, for example
   * <code>bar.*</code>.</p>
   */
  inline const Aws::Vector<Aws::String>& GetMessageAttributeNames() const { return m_messageAttributeNames; }
  inline bool MessageAttributeNamesHasBeenSet() const { return m_messageAttributeNamesHasBeenSet; }
  template <typename MessageAttributeNamesT = Aws::Vector<Aws::String>>
  void SetMessageAttributeNames(MessageAttributeNamesT&& value) {
    m_messageAttributeNamesHasBeenSet = true;
    m_messageAttributeNames = std::forward<MessageAttributeNamesT>(value);
  }
  template <typename MessageAttributeNamesT = Aws::Vector<Aws::String>>
  ReceiveMessageRequest& WithMessageAttributeNames(MessageAttributeNamesT&& value) {
    SetMessageAttributeNames(std::forward<MessageAttributeNamesT>(value));
    return *this;
  }
  template <typename MessageAttributeNamesT = Aws::String>
  ReceiveMessageRequest& AddMessageAttributeNames(MessageAttributeNamesT&& value) {
    m_messageAttributeNamesHasBeenSet = true;
    m_messageAttributeNames.emplace_back(std::forward<MessageAttributeNamesT>(value));
    return *this;
  }
  ///@}

  ///@{
  /**
   * <p>The maximum number of messages to return. Amazon SQS never returns more
   * messages than this value (however, fewer messages might be returned). Valid
   * values: 1 to 10. Default: 1.</p>
   */
  inline int GetMaxNumberOfMessages() const { return m_maxNumberOfMessages; }
  inline bool MaxNumberOfMessagesHasBeenSet() const { return m_maxNumberOfMessagesHasBeenSet; }
  inline void SetMaxNumberOfMessages(int value) {
    m_maxNumberOfMessagesHasBeenSet = true;
    m_maxNumberOfMessages = value;
  }
  inline ReceiveMessageRequest& WithMaxNumberOfMessages(int value) {
    SetMaxNumberOfMessages(value);
    return *this;
  }
  ///@}

  ///@{
  /**
   * <p>The duration (in seconds) that the received messages are hidden from
   * subsequent retrieve requests after being retrieved by a
   * <code>ReceiveMessage</code> request. If not specified, the default visibility
   * timeout for the queue is used, which is 30 seconds.</p> <p>Understanding
   * <code>VisibilityTimeout</code>:</p> <ul> <li> <p>When a message is received from
   * a queue, it becomes temporarily invisible to other consumers for the duration of
   * the visibility timeout. This prevents multiple consumers from processing the
   * same message simultaneously. If the message is not deleted or its visibility
   * timeout is not extended before the timeout expires, it becomes visible again and
   * can be retrieved by other consumers.</p> </li> <li> <p>Setting an appropriate
   * visibility timeout is crucial. If it's too short, the message might become
   * visible again before processing is complete, leading to duplicate processing. If
   * it's too long, it delays the reprocessing of messages if the initial processing
   * fails.</p> </li> <li> <p>You can adjust the visibility timeout using the
   * <code>--visibility-timeout</code> parameter in the <code>receive-message</code>
   * command to match the processing time required by your application.</p> </li>
   * <li> <p>A message that isn't deleted or a message whose visibility isn't
   * extended before the visibility timeout expires counts as a failed receive.
   * Depending on the configuration of the queue, the message might be sent to the
   * dead-letter queue.</p> </li> </ul> <p>For more information, see <a
   * href="https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-visibility-timeout.html">Visibility
   * Timeout</a> in the <i>Amazon SQS Developer Guide</i>.</p>
   */
  inline int GetVisibilityTimeout() const { return m_visibilityTimeout; }
  inline bool VisibilityTimeoutHasBeenSet() const { return m_visibilityTimeoutHasBeenSet; }
  inline void SetVisibilityTimeout(int value) {
    m_visibilityTimeoutHasBeenSet = true;
    m_visibilityTimeout = value;
  }
  inline ReceiveMessageRequest& WithVisibilityTimeout(int value) {
    SetVisibilityTimeout(value);
    return *this;
  }
  ///@}

  ///@{
  /**
   * <p>The duration (in seconds) for which the call waits for a message to arrive in
   * the queue before returning. If a message is available, the call returns sooner
   * than <code>WaitTimeSeconds</code>. If no messages are available and the wait
   * time expires, the call does not return a message list. If you are using the Java
   * SDK, it returns a <code>ReceiveMessageResponse</code> object, which has a empty
   * list instead of a Null object.</p>  <p>To avoid HTTP errors, ensure
   * that the HTTP response timeout for <code>ReceiveMessage</code> requests is
   * longer than the <code>WaitTimeSeconds</code> parameter. For example, with the
   * Java SDK, you can set HTTP transport settings using the <a
   * href="https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/nio/netty/NettyNioAsyncHttpClient.html">
   * NettyNioAsyncHttpClient</a> for asynchronous clients, or the <a
   * href="https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/apache/ApacheHttpClient.html">
   * ApacheHttpClient</a> for synchronous clients. </p>
   */
  inline int GetWaitTimeSeconds() const { return m_waitTimeSeconds; }
  inline bool WaitTimeSecondsHasBeenSet() const { return m_waitTimeSecondsHasBeenSet; }
  inline void SetWaitTimeSeconds(int value) {
    m_waitTimeSecondsHasBeenSet = true;
    m_waitTimeSeconds = value;
  }
  inline ReceiveMessageRequest& WithWaitTimeSeconds(int value) {
    SetWaitTimeSeconds(value);
    return *this;
  }
  ///@}

  ///@{
  /**
   * <p>This parameter applies only to FIFO (first-in-first-out) queues.</p> <p>The
   * token used for deduplication of <code>ReceiveMessage</code> calls. If a
   * networking issue occurs after a <code>ReceiveMessage</code> action, and instead
   * of a response you receive a generic error, it is possible to retry the same
   * action with an identical <code>ReceiveRequestAttemptId</code> to retrieve the
   * same set of messages, even if their visibility timeout has not yet expired.</p>
   * <ul> <li> <p>You can use <code>ReceiveRequestAttemptId</code> only for 5 minutes
   * after a <code>ReceiveMessage</code> action.</p> </li> <li> <p>When you set
   * <code>FifoQueue</code>, a caller of the <code>ReceiveMessage</code> action can
   * provide a <code>ReceiveRequestAttemptId</code> explicitly.</p> </li> <li> <p>It
   * is possible to retry the <code>ReceiveMessage</code> action with the same
   * <code>ReceiveRequestAttemptId</code> if none of the messages have been modified
   * (deleted or had their visibility changes).</p> </li> <li> <p>During a visibility
   * timeout, subsequent calls with the same <code>ReceiveRequestAttemptId</code>
   * return the same messages and receipt handles. If a retry occurs within the
   * deduplication interval, it resets the visibility timeout. For more information,
   * see <a
   * href="https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-visibility-timeout.html">Visibility
   * Timeout</a> in the <i>Amazon SQS Developer Guide</i>.</p>  <p>If a
   * caller of the <code>ReceiveMessage</code> action still processes messages when
   * the visibility timeout expires and messages become visible, another worker
   * consuming from the same queue can receive the same messages and therefore
   * process duplicates. Also, if a consumer whose message processing time is longer
   * than the visibility timeout tries to delete the processed messages, the action
   * fails with an error.</p> <p>To mitigate this effect, ensure that your
   * application observes a safe threshold before the visibility timeout expires and
   * extend the visibility timeout as necessary.</p>  </li> <li> <p>While
   * messages with a particular <code>MessageGroupId</code> are invisible, no more
   * messages belonging to the same <code>MessageGroupId</code> are returned until
   * the visibility timeout expires. You can still receive messages with another
   * <code>MessageGroupId</code> from your FIFO queue as long as they are
   * visible.</p> </li> <li> <p>If a caller of <code>ReceiveMessage</code> can't
   * track the <code>ReceiveRequestAttemptId</code>, no retries work until the
   * original visibility timeout expires. As a result, delays might occur but the
   * messages in the queue remain in a strict order.</p> </li> </ul> <p>The maximum
   * length of <code>ReceiveRequestAttemptId</code> is 128 characters.
   * <code>ReceiveRequestAttemptId</code> can contain alphanumeric characters
   * (<code>a-z</code>, <code>A-Z</code>, <code>0-9</code>) and punctuation
   * (<code>!"#$%&amp;'()*+,-./:;&lt;=&gt;?@[\]^_`{|}~</code>).</p> <p>For best
   * practices of using <code>ReceiveRequestAttemptId</code>, see <a
   * href="https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/using-receiverequestattemptid-request-parameter.html">Using
   * the ReceiveRequestAttemptId Request Parameter</a> in the <i>Amazon SQS Developer
   * Guide</i>.</p>
   */
  inline const Aws::String& GetReceiveRequestAttemptId() const { return m_receiveRequestAttemptId; }
  inline bool ReceiveRequestAttemptIdHasBeenSet() const { return m_receiveRequestAttemptIdHasBeenSet; }
  template <typename ReceiveRequestAttemptIdT = Aws::String>
  void SetReceiveRequestAttemptId(ReceiveRequestAttemptIdT&& value) {
    m_receiveRequestAttemptIdHasBeenSet = true;
    m_receiveRequestAttemptId = std::forward<ReceiveRequestAttemptIdT>(value);
  }
  template <typename ReceiveRequestAttemptIdT = Aws::String>
  ReceiveMessageRequest& WithReceiveRequestAttemptId(ReceiveRequestAttemptIdT&& value) {
    SetReceiveRequestAttemptId(std::forward<ReceiveRequestAttemptIdT>(value));
    return *this;
  }
  ///@}
 private:
  Aws::String m_queueUrl;

  Aws::Vector<MessageSystemAttributeName> m_messageSystemAttributeNames;

  Aws::Vector<Aws::String> m_messageAttributeNames;

  int m_maxNumberOfMessages{0};

  int m_visibilityTimeout{0};

  int m_waitTimeSeconds{0};

  Aws::String m_receiveRequestAttemptId;
  bool m_queueUrlHasBeenSet = false;
  bool m_messageSystemAttributeNamesHasBeenSet = false;
  bool m_messageAttributeNamesHasBeenSet = false;
  bool m_maxNumberOfMessagesHasBeenSet = false;
  bool m_visibilityTimeoutHasBeenSet = false;
  bool m_waitTimeSecondsHasBeenSet = false;
  bool m_receiveRequestAttemptIdHasBeenSet = false;
};

}  // namespace Model
}  // namespace SQS
}  // namespace Aws
