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

#pragma once
#include <aws/ce/CostExplorerRequest.h>
#include <aws/ce/CostExplorer_EXPORTS.h>
#include <aws/ce/model/DateInterval.h>
#include <aws/ce/model/Expression.h>
#include <aws/ce/model/Granularity.h>
#include <aws/ce/model/GroupDefinition.h>
#include <aws/core/utils/memory/stl/AWSString.h>
#include <aws/core/utils/memory/stl/AWSVector.h>

#include <utility>

namespace Aws {
namespace CostExplorer {
namespace Model {

/**
 */
class GetCostAndUsageRequest : public CostExplorerRequest {
 public:
  AWS_COSTEXPLORER_API GetCostAndUsageRequest() = 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 "GetCostAndUsage"; }

  AWS_COSTEXPLORER_API Aws::String SerializePayload() const override;

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

  ///@{
  /**
   * <p>Sets the start date and end date for retrieving Amazon Web Services costs.
   * The start date is inclusive, but the end date is exclusive. For example, if
   * <code>start</code> is <code>2017-01-01</code> and <code>end</code> is
   * <code>2017-05-01</code>, then the cost and usage data is retrieved from
   * <code>2017-01-01</code> up to and including <code>2017-04-30</code> but not
   * including <code>2017-05-01</code>.</p>
   */
  inline const DateInterval& GetTimePeriod() const { return m_timePeriod; }
  inline bool TimePeriodHasBeenSet() const { return m_timePeriodHasBeenSet; }
  template <typename TimePeriodT = DateInterval>
  void SetTimePeriod(TimePeriodT&& value) {
    m_timePeriodHasBeenSet = true;
    m_timePeriod = std::forward<TimePeriodT>(value);
  }
  template <typename TimePeriodT = DateInterval>
  GetCostAndUsageRequest& WithTimePeriod(TimePeriodT&& value) {
    SetTimePeriod(std::forward<TimePeriodT>(value));
    return *this;
  }
  ///@}

  ///@{
  /**
   * <p>Sets the Amazon Web Services cost granularity to <code>MONTHLY</code> or
   * <code>DAILY</code>, or <code>HOURLY</code>. If <code>Granularity</code> isn't
   * set, the response object doesn't include the <code>Granularity</code>, either
   * <code>MONTHLY</code> or <code>DAILY</code>, or <code>HOURLY</code>. </p>
   */
  inline Granularity GetGranularity() const { return m_granularity; }
  inline bool GranularityHasBeenSet() const { return m_granularityHasBeenSet; }
  inline void SetGranularity(Granularity value) {
    m_granularityHasBeenSet = true;
    m_granularity = value;
  }
  inline GetCostAndUsageRequest& WithGranularity(Granularity value) {
    SetGranularity(value);
    return *this;
  }
  ///@}

  ///@{
  /**
   * <p>Filters Amazon Web Services costs by different dimensions. For example, you
   * can specify <code>SERVICE</code> and <code>LINKED_ACCOUNT</code> and get the
   * costs that are associated with that account's usage of that service. You can
   * nest <code>Expression</code> objects to define any combination of dimension
   * filters. For more information, see <a
   * href="https://docs.aws.amazon.com/aws-cost-management/latest/APIReference/API_Expression.html">Expression</a>.
   * </p> <p>Valid values for <code>MatchOptions</code> for <code>Dimensions</code>
   * are <code>EQUALS</code> and <code>CASE_SENSITIVE</code>.</p> <p>Valid values for
   * <code>MatchOptions</code> for <code>CostCategories</code> and <code>Tags</code>
   * are <code>EQUALS</code>, <code>ABSENT</code>, and <code>CASE_SENSITIVE</code>.
   * Default values are <code>EQUALS</code> and <code>CASE_SENSITIVE</code>.</p>
   */
  inline const Expression& GetFilter() const { return m_filter; }
  inline bool FilterHasBeenSet() const { return m_filterHasBeenSet; }
  template <typename FilterT = Expression>
  void SetFilter(FilterT&& value) {
    m_filterHasBeenSet = true;
    m_filter = std::forward<FilterT>(value);
  }
  template <typename FilterT = Expression>
  GetCostAndUsageRequest& WithFilter(FilterT&& value) {
    SetFilter(std::forward<FilterT>(value));
    return *this;
  }
  ///@}

  ///@{
  /**
   * <p>Which metrics are returned in the query. For more information about blended
   * and unblended rates, see <a
   * href="http://aws.amazon.com/premiumsupport/knowledge-center/blended-rates-intro/">Why
   * does the "blended" annotation appear on some line items in my bill?</a>. </p>
   * <p>Valid values are <code>AmortizedCost</code>, <code>BlendedCost</code>,
   * <code>NetAmortizedCost</code>, <code>NetUnblendedCost</code>,
   * <code>NormalizedUsageAmount</code>, <code>UnblendedCost</code>, and
   * <code>UsageQuantity</code>. </p>  <p>If you return the
   * <code>UsageQuantity</code> metric, the service aggregates all usage numbers
   * without taking into account the units. For example, if you aggregate
   * <code>usageQuantity</code> across all of Amazon EC2, the results aren't
   * meaningful because Amazon EC2 compute hours and data transfer are measured in
   * different units (for example, hours and GB). To get more meaningful
   * <code>UsageQuantity</code> metrics, filter by <code>UsageType</code> or
   * <code>UsageTypeGroups</code>. </p>  <p> <code>Metrics</code> is required
   * for <code>GetCostAndUsage</code> requests.</p>
   */
  inline const Aws::Vector<Aws::String>& GetMetrics() const { return m_metrics; }
  inline bool MetricsHasBeenSet() const { return m_metricsHasBeenSet; }
  template <typename MetricsT = Aws::Vector<Aws::String>>
  void SetMetrics(MetricsT&& value) {
    m_metricsHasBeenSet = true;
    m_metrics = std::forward<MetricsT>(value);
  }
  template <typename MetricsT = Aws::Vector<Aws::String>>
  GetCostAndUsageRequest& WithMetrics(MetricsT&& value) {
    SetMetrics(std::forward<MetricsT>(value));
    return *this;
  }
  template <typename MetricsT = Aws::String>
  GetCostAndUsageRequest& AddMetrics(MetricsT&& value) {
    m_metricsHasBeenSet = true;
    m_metrics.emplace_back(std::forward<MetricsT>(value));
    return *this;
  }
  ///@}

  ///@{
  /**
   * <p>You can group Amazon Web Services costs using up to two different groups,
   * either dimensions, tag keys, cost categories, or any two group by types.</p>
   * <p>Valid values for the <code>DIMENSION</code> type are <code>AZ</code>,
   * <code>INSTANCE_TYPE</code>, <code>LEGAL_ENTITY_NAME</code>,
   * <code>INVOICING_ENTITY</code>, <code>LINKED_ACCOUNT</code>,
   * <code>OPERATION</code>, <code>PLATFORM</code>, <code>PURCHASE_TYPE</code>,
   * <code>SERVICE</code>, <code>TENANCY</code>, <code>RECORD_TYPE</code>, and
   * <code>USAGE_TYPE</code>.</p> <p>When you group by the <code>TAG</code> type and
   * include a valid tag key, you get all tag values, including empty strings.</p>
   */
  inline const Aws::Vector<GroupDefinition>& GetGroupBy() const { return m_groupBy; }
  inline bool GroupByHasBeenSet() const { return m_groupByHasBeenSet; }
  template <typename GroupByT = Aws::Vector<GroupDefinition>>
  void SetGroupBy(GroupByT&& value) {
    m_groupByHasBeenSet = true;
    m_groupBy = std::forward<GroupByT>(value);
  }
  template <typename GroupByT = Aws::Vector<GroupDefinition>>
  GetCostAndUsageRequest& WithGroupBy(GroupByT&& value) {
    SetGroupBy(std::forward<GroupByT>(value));
    return *this;
  }
  template <typename GroupByT = GroupDefinition>
  GetCostAndUsageRequest& AddGroupBy(GroupByT&& value) {
    m_groupByHasBeenSet = true;
    m_groupBy.emplace_back(std::forward<GroupByT>(value));
    return *this;
  }
  ///@}

  ///@{
  /**
   * <p>The Amazon Resource Name (ARN) that uniquely identifies a specific billing
   * view. The ARN is used to specify which particular billing view you want to
   * interact with or retrieve information from when making API calls related to
   * Amazon Web Services Billing and Cost Management features. The BillingViewArn can
   * be retrieved by calling the ListBillingViews API.</p>
   */
  inline const Aws::String& GetBillingViewArn() const { return m_billingViewArn; }
  inline bool BillingViewArnHasBeenSet() const { return m_billingViewArnHasBeenSet; }
  template <typename BillingViewArnT = Aws::String>
  void SetBillingViewArn(BillingViewArnT&& value) {
    m_billingViewArnHasBeenSet = true;
    m_billingViewArn = std::forward<BillingViewArnT>(value);
  }
  template <typename BillingViewArnT = Aws::String>
  GetCostAndUsageRequest& WithBillingViewArn(BillingViewArnT&& value) {
    SetBillingViewArn(std::forward<BillingViewArnT>(value));
    return *this;
  }
  ///@}

  ///@{
  /**
   * <p>The token to retrieve the next set of results. Amazon Web Services provides
   * the token when the response from a previous call has more results than the
   * maximum page size.</p>
   */
  inline const Aws::String& GetNextPageToken() const { return m_nextPageToken; }
  inline bool NextPageTokenHasBeenSet() const { return m_nextPageTokenHasBeenSet; }
  template <typename NextPageTokenT = Aws::String>
  void SetNextPageToken(NextPageTokenT&& value) {
    m_nextPageTokenHasBeenSet = true;
    m_nextPageToken = std::forward<NextPageTokenT>(value);
  }
  template <typename NextPageTokenT = Aws::String>
  GetCostAndUsageRequest& WithNextPageToken(NextPageTokenT&& value) {
    SetNextPageToken(std::forward<NextPageTokenT>(value));
    return *this;
  }
  ///@}
 private:
  DateInterval m_timePeriod;
  bool m_timePeriodHasBeenSet = false;

  Granularity m_granularity{Granularity::NOT_SET};
  bool m_granularityHasBeenSet = false;

  Expression m_filter;
  bool m_filterHasBeenSet = false;

  Aws::Vector<Aws::String> m_metrics;
  bool m_metricsHasBeenSet = false;

  Aws::Vector<GroupDefinition> m_groupBy;
  bool m_groupByHasBeenSet = false;

  Aws::String m_billingViewArn;
  bool m_billingViewArnHasBeenSet = false;

  Aws::String m_nextPageToken;
  bool m_nextPageTokenHasBeenSet = false;
};

}  // namespace Model
}  // namespace CostExplorer
}  // namespace Aws
