// Code generated by sidekick. DO NOT EDIT.
//
// Copyright 2026 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import Foundation
import GoogleCloudWkt

/// Describes how to combine multiple time series to provide a different view of
/// the data.  Aggregation of time series is done in two steps. First, each time
/// series in the set is _aligned_ to the same time interval boundaries, then the
/// set of time series is optionally _reduced_ in number.
///
/// Alignment consists of applying the `per_series_aligner` operation
/// to each time series after its data has been divided into regular
/// `alignment_period` time intervals. This process takes _all_ of the data
/// points in an alignment period, applies a mathematical transformation such as
/// averaging, minimum, maximum, delta, etc., and converts them into a single
/// data point per period.
///
/// Reduction is when the aligned and transformed time series can optionally be
/// combined, reducing the number of time series through similar mathematical
/// transformations. Reduction involves applying a `cross_series_reducer` to
/// all the time series, optionally sorting the time series into subsets with
/// `group_by_fields`, and applying the reducer to each subset.
///
/// The raw time series data can contain a huge amount of information from
/// multiple sources. Alignment and reduction transforms this mass of data into
/// a more manageable and representative collection of data, for example "the
/// 95% latency across the average of all tasks in a cluster". This
/// representative data can be more easily graphed and comprehended, and the
/// individual time series data is still available for later drilldown. For more
/// details, see [Filtering and
/// aggregation](https://cloud.google.com/monitoring/api/v3/aggregation).
public struct Aggregation: Codable, Equatable, GoogleCloudWkt._AnyPackable,
  Sendable
{
  /// The `alignment_period` specifies a time interval, in seconds, that is used
  /// to divide the data in all the
  /// [time series][google.monitoring.v3.TimeSeries] into consistent blocks of
  /// time. This will be done before the per-series aligner can be applied to
  /// the data.
  ///
  /// The value must be at least 60 seconds. If a per-series aligner other than
  /// `ALIGN_NONE` is specified, this field is required or an error is returned.
  /// If no per-series aligner is specified, or the aligner `ALIGN_NONE` is
  /// specified, then this field is ignored.
  ///
  /// The maximum value of the `alignment_period` is 2 years, or 104 weeks.
  public var alignmentPeriod: GoogleCloudWkt.Duration? = nil

  /// An `Aligner` describes how to bring the data points in a single
  /// time series into temporal alignment. Except for `ALIGN_NONE`, all
  /// alignments cause all the data points in an `alignment_period` to be
  /// mathematically grouped together, resulting in a single data point for
  /// each `alignment_period` with end timestamp at the end of the period.
  ///
  /// Not all alignment operations may be applied to all time series. The valid
  /// choices depend on the `metric_kind` and `value_type` of the original time
  /// series. Alignment can change the `metric_kind` or the `value_type` of
  /// the time series.
  ///
  /// Time series data must be aligned in order to perform cross-time
  /// series reduction. If `cross_series_reducer` is specified, then
  /// `per_series_aligner` must be specified and not equal to `ALIGN_NONE`
  /// and `alignment_period` must be specified; otherwise, an error is
  /// returned.
  public var perSeriesAligner: Aggregation.Aligner = Aggregation.Aligner()

  /// The reduction operation to be used to combine time series into a single
  /// time series, where the value of each data point in the resulting series is
  /// a function of all the already aligned values in the input time series.
  ///
  /// Not all reducer operations can be applied to all time series. The valid
  /// choices depend on the `metric_kind` and the `value_type` of the original
  /// time series. Reduction can yield a time series with a different
  /// `metric_kind` or `value_type` than the input time series.
  ///
  /// Time series data must first be aligned (see `per_series_aligner`) in order
  /// to perform cross-time series reduction. If `cross_series_reducer` is
  /// specified, then `per_series_aligner` must be specified, and must not be
  /// `ALIGN_NONE`. An `alignment_period` must also be specified; otherwise, an
  /// error is returned.
  public var crossSeriesReducer: Aggregation.Reducer = Aggregation.Reducer()

  /// The set of fields to preserve when `cross_series_reducer` is
  /// specified. The `group_by_fields` determine how the time series are
  /// partitioned into subsets prior to applying the aggregation
  /// operation. Each subset contains time series that have the same
  /// value for each of the grouping fields. Each individual time
  /// series is a member of exactly one subset. The
  /// `cross_series_reducer` is applied to each subset of time series.
  /// It is not possible to reduce across different resource types, so
  /// this field implicitly contains `resource.type`.  Fields not
  /// specified in `group_by_fields` are aggregated away.  If
  /// `group_by_fields` is not specified and all the time series have
  /// the same resource type, then the time series are aggregated into
  /// a single output time series. If `cross_series_reducer` is not
  /// defined, this field is ignored.
  public var groupByFields: [Swift.String] = []

  /// Initialize a new instance of `Aggregation`.
  public init() {}

  /// Use `config` to return a new instance of this object, with some fields updated.
  ///
  /// Commonly used to initialize the value, for example:
  ///
  /// ```
  /// let value = Aggregation().with { $0.alignmentPeriod = ... }
  /// ```
  public func with(_ config: (inout Self) throws -> Swift.Void) rethrows -> Self {
    var copy = self
    try config(&copy)
    return copy
  }

  /// The `Aligner` specifies the operation that will be applied to the data
  /// points in each alignment period in a time series. Except for
  /// `ALIGN_NONE`, which specifies that no operation be applied, each alignment
  /// operation replaces the set of data values in each alignment period with
  /// a single value: the result of applying the operation to the data values.
  /// An aligned time series has a single data value at the end of each
  /// `alignment_period`.
  ///
  /// An alignment operation can change the data type of the values, too. For
  /// example, if you apply a counting operation to boolean values, the data
  /// `value_type` in the original time series is `BOOLEAN`, but the `value_type`
  /// in the aligned result is `INT64`.
  public enum Aligner: Codable, Equatable, Sendable {
    /// No alignment. Raw data is returned. Not valid if cross-series reduction
    /// is requested. The `value_type` of the result is the same as the
    /// `value_type` of the input.
    case alignNone
    /// Align and convert to
    /// [DELTA][google.api.MetricDescriptor.MetricKind.DELTA].
    /// The output is `delta = y1 - y0`.
    ///
    /// This alignment is valid for
    /// [CUMULATIVE][google.api.MetricDescriptor.MetricKind.CUMULATIVE] and
    /// `DELTA` metrics. If the selected alignment period results in periods
    /// with no data, then the aligned value for such a period is created by
    /// interpolation. The `value_type`  of the aligned result is the same as
    /// the `value_type` of the input.
    case alignDelta
    /// Align and convert to a rate. The result is computed as
    /// `rate = (y1 - y0)/(t1 - t0)`, or "delta over time".
    /// Think of this aligner as providing the slope of the line that passes
    /// through the value at the start and at the end of the `alignment_period`.
    ///
    /// This aligner is valid for `CUMULATIVE`
    /// and `DELTA` metrics with numeric values. If the selected alignment
    /// period results in periods with no data, then the aligned value for
    /// such a period is created by interpolation. The output is a `GAUGE`
    /// metric with `value_type` `DOUBLE`.
    ///
    /// If, by "rate", you mean "percentage change", see the
    /// `ALIGN_PERCENT_CHANGE` aligner instead.
    case alignRate
    /// Align by interpolating between adjacent points around the alignment
    /// period boundary. This aligner is valid for `GAUGE` metrics with
    /// numeric values. The `value_type` of the aligned result is the same as the
    /// `value_type` of the input.
    case alignInterpolate
    /// Align by moving the most recent data point before the end of the
    /// alignment period to the boundary at the end of the alignment
    /// period. This aligner is valid for `GAUGE` metrics. The `value_type` of
    /// the aligned result is the same as the `value_type` of the input.
    case alignNextOlder
    /// Align the time series by returning the minimum value in each alignment
    /// period. This aligner is valid for `GAUGE` and `DELTA` metrics with
    /// numeric values. The `value_type` of the aligned result is the same as
    /// the `value_type` of the input.
    case alignMin
    /// Align the time series by returning the maximum value in each alignment
    /// period. This aligner is valid for `GAUGE` and `DELTA` metrics with
    /// numeric values. The `value_type` of the aligned result is the same as
    /// the `value_type` of the input.
    case alignMax
    /// Align the time series by returning the mean value in each alignment
    /// period. This aligner is valid for `GAUGE` and `DELTA` metrics with
    /// numeric values. The `value_type` of the aligned result is `DOUBLE`.
    case alignMean
    /// Align the time series by returning the number of values in each alignment
    /// period. This aligner is valid for `GAUGE` and `DELTA` metrics with
    /// numeric or Boolean values. The `value_type` of the aligned result is
    /// `INT64`.
    case alignCount
    /// Align the time series by returning the sum of the values in each
    /// alignment period. This aligner is valid for `GAUGE` and `DELTA`
    /// metrics with numeric and distribution values. The `value_type` of the
    /// aligned result is the same as the `value_type` of the input.
    case alignSum
    /// Align the time series by returning the standard deviation of the values
    /// in each alignment period. This aligner is valid for `GAUGE` and
    /// `DELTA` metrics with numeric values. The `value_type` of the output is
    /// `DOUBLE`.
    case alignStddev
    /// Align the time series by returning the number of `True` values in
    /// each alignment period. This aligner is valid for `GAUGE` metrics with
    /// Boolean values. The `value_type` of the output is `INT64`.
    case alignCountTrue
    /// Align the time series by returning the ratio of the number of `True`
    /// values to the total number of values in each alignment period. This
    /// aligner is valid for `GAUGE` metrics with Boolean values. The output
    /// value is in the range [0.0, 1.0] and has `value_type` `DOUBLE`.
    case alignFractionTrue
    /// Align the time series by using [percentile
    /// aggregation](https://en.wikipedia.org/wiki/Percentile). The resulting
    /// data point in each alignment period is the 99th percentile of all data
    /// points in the period. This aligner is valid for `GAUGE` and `DELTA`
    /// metrics with distribution values. The output is a `GAUGE` metric with
    /// `value_type` `DOUBLE`.
    case alignPercentile99
    /// Align the time series by using [percentile
    /// aggregation](https://en.wikipedia.org/wiki/Percentile). The resulting
    /// data point in each alignment period is the 95th percentile of all data
    /// points in the period. This aligner is valid for `GAUGE` and `DELTA`
    /// metrics with distribution values. The output is a `GAUGE` metric with
    /// `value_type` `DOUBLE`.
    case alignPercentile95
    /// Align the time series by using [percentile
    /// aggregation](https://en.wikipedia.org/wiki/Percentile). The resulting
    /// data point in each alignment period is the 50th percentile of all data
    /// points in the period. This aligner is valid for `GAUGE` and `DELTA`
    /// metrics with distribution values. The output is a `GAUGE` metric with
    /// `value_type` `DOUBLE`.
    case alignPercentile50
    /// Align the time series by using [percentile
    /// aggregation](https://en.wikipedia.org/wiki/Percentile). The resulting
    /// data point in each alignment period is the 5th percentile of all data
    /// points in the period. This aligner is valid for `GAUGE` and `DELTA`
    /// metrics with distribution values. The output is a `GAUGE` metric with
    /// `value_type` `DOUBLE`.
    case alignPercentile05
    /// Align and convert to a percentage change. This aligner is valid for
    /// `GAUGE` and `DELTA` metrics with numeric values. This alignment returns
    /// `((current - previous)/previous) * 100`, where the value of `previous` is
    /// determined based on the `alignment_period`.
    ///
    /// If the values of `current` and `previous` are both 0, then the returned
    /// value is 0. If only `previous` is 0, the returned value is infinity.
    ///
    /// A 10-minute moving mean is computed at each point of the alignment period
    /// prior to the above calculation to smooth the metric and prevent false
    /// positives from very short-lived spikes. The moving mean is only
    /// applicable for data whose values are `>= 0`. Any values `< 0` are
    /// treated as a missing datapoint, and are ignored. While `DELTA`
    /// metrics are accepted by this alignment, special care should be taken that
    /// the values for the metric will always be positive. The output is a
    /// `GAUGE` metric with `value_type` `DOUBLE`.
    case alignPercentChange
    /// Align the time series by returning the number of `False` values in
    /// each alignment period. This aligner is valid for `GAUGE` metrics with
    /// Boolean values. The `value_type` of the output is `INT64`.
    case alignCountFalse
    /// Encodes an unknown integer value.
    ///
    /// The most common cause for an unknown values is for the service to send
    /// a value unknown to the library. We recommend you update your library to
    /// the latest version.
    case unknownIntValue(Int)
    /// Encodes an unknown string value.
    ///
    /// The most common cause for an unknown values is for the service to send
    /// a value unknown to the library. We recommend you update your library to
    /// the latest version.
    case unknownStringValue(String)

    public init() {
      self = .alignNone
    }

    /// Returns the integer value associated with the enumeration.
    ///
    /// If the enumeration was initialized with an unknown string value, this returns `nil`.
    public var intValue: Int? {
      switch self {
      case .alignNone: return 0
      case .alignDelta: return 1
      case .alignRate: return 2
      case .alignInterpolate: return 3
      case .alignNextOlder: return 4
      case .alignMin: return 10
      case .alignMax: return 11
      case .alignMean: return 12
      case .alignCount: return 13
      case .alignSum: return 14
      case .alignStddev: return 15
      case .alignCountTrue: return 16
      case .alignFractionTrue: return 17
      case .alignPercentile99: return 18
      case .alignPercentile95: return 19
      case .alignPercentile50: return 20
      case .alignPercentile05: return 21
      case .alignPercentChange: return 23
      case .alignCountFalse: return 24
      case .unknownIntValue(let v): return v
      case .unknownStringValue: return nil
      }
    }

    /// Returns the string value (or name) associated with the enumeration.
    ///
    /// If the enumeration was initialized with an unknown integer value, this returns `nil`.
    public var stringValue: Swift.String? {
      switch self {
      case .alignNone: return "ALIGN_NONE"
      case .alignDelta: return "ALIGN_DELTA"
      case .alignRate: return "ALIGN_RATE"
      case .alignInterpolate: return "ALIGN_INTERPOLATE"
      case .alignNextOlder: return "ALIGN_NEXT_OLDER"
      case .alignMin: return "ALIGN_MIN"
      case .alignMax: return "ALIGN_MAX"
      case .alignMean: return "ALIGN_MEAN"
      case .alignCount: return "ALIGN_COUNT"
      case .alignSum: return "ALIGN_SUM"
      case .alignStddev: return "ALIGN_STDDEV"
      case .alignCountTrue: return "ALIGN_COUNT_TRUE"
      case .alignFractionTrue: return "ALIGN_FRACTION_TRUE"
      case .alignPercentile99: return "ALIGN_PERCENTILE_99"
      case .alignPercentile95: return "ALIGN_PERCENTILE_95"
      case .alignPercentile50: return "ALIGN_PERCENTILE_50"
      case .alignPercentile05: return "ALIGN_PERCENTILE_05"
      case .alignPercentChange: return "ALIGN_PERCENT_CHANGE"
      case .alignCountFalse: return "ALIGN_COUNT_FALSE"
      case .unknownIntValue: return nil
      case .unknownStringValue(let v): return v
      }
    }

    /// Initialize from a string value.
    ///
    /// If the value is unknown, this initializes to [`unknownStringValue`](doc:Aligner/unknownStringValue(_:)).
    public init(stringValue: Swift.String) {
      switch stringValue {
      case "ALIGN_NONE": self = .alignNone
      case "ALIGN_DELTA": self = .alignDelta
      case "ALIGN_RATE": self = .alignRate
      case "ALIGN_INTERPOLATE": self = .alignInterpolate
      case "ALIGN_NEXT_OLDER": self = .alignNextOlder
      case "ALIGN_MIN": self = .alignMin
      case "ALIGN_MAX": self = .alignMax
      case "ALIGN_MEAN": self = .alignMean
      case "ALIGN_COUNT": self = .alignCount
      case "ALIGN_SUM": self = .alignSum
      case "ALIGN_STDDEV": self = .alignStddev
      case "ALIGN_COUNT_TRUE": self = .alignCountTrue
      case "ALIGN_COUNT_FALSE": self = .alignCountFalse
      case "ALIGN_FRACTION_TRUE": self = .alignFractionTrue
      case "ALIGN_PERCENTILE_99": self = .alignPercentile99
      case "ALIGN_PERCENTILE_95": self = .alignPercentile95
      case "ALIGN_PERCENTILE_50": self = .alignPercentile50
      case "ALIGN_PERCENTILE_05": self = .alignPercentile05
      case "ALIGN_PERCENT_CHANGE": self = .alignPercentChange
      default: self = .unknownStringValue(stringValue)
      }
    }

    /// Initialize from an integer value.
    ///
    /// If the value is unknown, this initializes to [`unknownIntValue`](doc:Aligner/unknownIntValue(_:)).
    public init(intValue: Int) {
      switch intValue {
      case 0: self = .alignNone
      case 1: self = .alignDelta
      case 2: self = .alignRate
      case 3: self = .alignInterpolate
      case 4: self = .alignNextOlder
      case 10: self = .alignMin
      case 11: self = .alignMax
      case 12: self = .alignMean
      case 13: self = .alignCount
      case 14: self = .alignSum
      case 15: self = .alignStddev
      case 16: self = .alignCountTrue
      case 17: self = .alignFractionTrue
      case 18: self = .alignPercentile99
      case 19: self = .alignPercentile95
      case 20: self = .alignPercentile50
      case 21: self = .alignPercentile05
      case 23: self = .alignPercentChange
      case 24: self = .alignCountFalse
      default: self = .unknownIntValue(intValue)
      }
    }

    public init(from decoder: Decoder) throws {
      let container = try decoder.singleValueContainer()
      if let v = try? container.decode(Int.self) {
        self.init(intValue: v)
        return
      }
      if let s = try? container.decode(String.self) {
        if let v = Int(s) {
          self.init(intValue: v)
        } else {
          self.init(stringValue: s)
        }
        return
      }
      throw DecodingError.dataCorruptedError(
        in: container, debugDescription: "Expected enum value, must be integer or string.")
    }

    public func encode(to encoder: Encoder) throws {
      var container = encoder.singleValueContainer()
      switch self {
      case .alignNone: return try container.encode(0)
      case .alignDelta: return try container.encode(1)
      case .alignRate: return try container.encode(2)
      case .alignInterpolate: return try container.encode(3)
      case .alignNextOlder: return try container.encode(4)
      case .alignMin: return try container.encode(10)
      case .alignMax: return try container.encode(11)
      case .alignMean: return try container.encode(12)
      case .alignCount: return try container.encode(13)
      case .alignSum: return try container.encode(14)
      case .alignStddev: return try container.encode(15)
      case .alignCountTrue: return try container.encode(16)
      case .alignFractionTrue: return try container.encode(17)
      case .alignPercentile99: return try container.encode(18)
      case .alignPercentile95: return try container.encode(19)
      case .alignPercentile50: return try container.encode(20)
      case .alignPercentile05: return try container.encode(21)
      case .alignPercentChange: return try container.encode(23)
      case .alignCountFalse: return try container.encode(24)
      case .unknownIntValue(let v): return try container.encode(v)
      case .unknownStringValue(let v): return try container.encode(v)
      }
    }
  }

  /// A Reducer operation describes how to aggregate data points from multiple
  /// time series into a single time series, where the value of each data point
  /// in the resulting series is a function of all the already aligned values in
  /// the input time series.
  public enum Reducer: Codable, Equatable, Sendable {
    /// No cross-time series reduction. The output of the `Aligner` is
    /// returned.
    case reduceNone
    /// Reduce by computing the mean value across time series for each
    /// alignment period. This reducer is valid for
    /// [DELTA][google.api.MetricDescriptor.MetricKind.DELTA] and
    /// [GAUGE][google.api.MetricDescriptor.MetricKind.GAUGE] metrics with
    /// numeric or distribution values. The `value_type` of the output is
    /// [DOUBLE][google.api.MetricDescriptor.ValueType.DOUBLE].
    case reduceMean
    /// Reduce by computing the minimum value across time series for each
    /// alignment period. This reducer is valid for `DELTA` and `GAUGE` metrics
    /// with numeric values. The `value_type` of the output is the same as the
    /// `value_type` of the input.
    case reduceMin
    /// Reduce by computing the maximum value across time series for each
    /// alignment period. This reducer is valid for `DELTA` and `GAUGE` metrics
    /// with numeric values. The `value_type` of the output is the same as the
    /// `value_type` of the input.
    case reduceMax
    /// Reduce by computing the sum across time series for each
    /// alignment period. This reducer is valid for `DELTA` and `GAUGE` metrics
    /// with numeric and distribution values. The `value_type` of the output is
    /// the same as the `value_type` of the input.
    case reduceSum
    /// Reduce by computing the standard deviation across time series
    /// for each alignment period. This reducer is valid for `DELTA` and
    /// `GAUGE` metrics with numeric or distribution values. The `value_type`
    /// of the output is `DOUBLE`.
    case reduceStddev
    /// Reduce by computing the number of data points across time series
    /// for each alignment period. This reducer is valid for `DELTA` and
    /// `GAUGE` metrics of numeric, Boolean, distribution, and string
    /// `value_type`. The `value_type` of the output is `INT64`.
    case reduceCount
    /// Reduce by computing the number of `True`-valued data points across time
    /// series for each alignment period. This reducer is valid for `DELTA` and
    /// `GAUGE` metrics of Boolean `value_type`. The `value_type` of the output
    /// is `INT64`.
    case reduceCountTrue
    /// Reduce by computing the ratio of the number of `True`-valued data points
    /// to the total number of data points for each alignment period. This
    /// reducer is valid for `DELTA` and `GAUGE` metrics of Boolean `value_type`.
    /// The output value is in the range [0.0, 1.0] and has `value_type`
    /// `DOUBLE`.
    case reduceFractionTrue
    /// Reduce by computing the [99th
    /// percentile](https://en.wikipedia.org/wiki/Percentile) of data points
    /// across time series for each alignment period. This reducer is valid for
    /// `GAUGE` and `DELTA` metrics of numeric and distribution type. The value
    /// of the output is `DOUBLE`.
    case reducePercentile99
    /// Reduce by computing the [95th
    /// percentile](https://en.wikipedia.org/wiki/Percentile) of data points
    /// across time series for each alignment period. This reducer is valid for
    /// `GAUGE` and `DELTA` metrics of numeric and distribution type. The value
    /// of the output is `DOUBLE`.
    case reducePercentile95
    /// Reduce by computing the [50th
    /// percentile](https://en.wikipedia.org/wiki/Percentile) of data points
    /// across time series for each alignment period. This reducer is valid for
    /// `GAUGE` and `DELTA` metrics of numeric and distribution type. The value
    /// of the output is `DOUBLE`.
    case reducePercentile50
    /// Reduce by computing the [5th
    /// percentile](https://en.wikipedia.org/wiki/Percentile) of data points
    /// across time series for each alignment period. This reducer is valid for
    /// `GAUGE` and `DELTA` metrics of numeric and distribution type. The value
    /// of the output is `DOUBLE`.
    case reducePercentile05
    /// Reduce by computing the number of `False`-valued data points across time
    /// series for each alignment period. This reducer is valid for `DELTA` and
    /// `GAUGE` metrics of Boolean `value_type`. The `value_type` of the output
    /// is `INT64`.
    case reduceCountFalse
    /// Encodes an unknown integer value.
    ///
    /// The most common cause for an unknown values is for the service to send
    /// a value unknown to the library. We recommend you update your library to
    /// the latest version.
    case unknownIntValue(Int)
    /// Encodes an unknown string value.
    ///
    /// The most common cause for an unknown values is for the service to send
    /// a value unknown to the library. We recommend you update your library to
    /// the latest version.
    case unknownStringValue(String)

    public init() {
      self = .reduceNone
    }

    /// Returns the integer value associated with the enumeration.
    ///
    /// If the enumeration was initialized with an unknown string value, this returns `nil`.
    public var intValue: Int? {
      switch self {
      case .reduceNone: return 0
      case .reduceMean: return 1
      case .reduceMin: return 2
      case .reduceMax: return 3
      case .reduceSum: return 4
      case .reduceStddev: return 5
      case .reduceCount: return 6
      case .reduceCountTrue: return 7
      case .reduceFractionTrue: return 8
      case .reducePercentile99: return 9
      case .reducePercentile95: return 10
      case .reducePercentile50: return 11
      case .reducePercentile05: return 12
      case .reduceCountFalse: return 15
      case .unknownIntValue(let v): return v
      case .unknownStringValue: return nil
      }
    }

    /// Returns the string value (or name) associated with the enumeration.
    ///
    /// If the enumeration was initialized with an unknown integer value, this returns `nil`.
    public var stringValue: Swift.String? {
      switch self {
      case .reduceNone: return "REDUCE_NONE"
      case .reduceMean: return "REDUCE_MEAN"
      case .reduceMin: return "REDUCE_MIN"
      case .reduceMax: return "REDUCE_MAX"
      case .reduceSum: return "REDUCE_SUM"
      case .reduceStddev: return "REDUCE_STDDEV"
      case .reduceCount: return "REDUCE_COUNT"
      case .reduceCountTrue: return "REDUCE_COUNT_TRUE"
      case .reduceFractionTrue: return "REDUCE_FRACTION_TRUE"
      case .reducePercentile99: return "REDUCE_PERCENTILE_99"
      case .reducePercentile95: return "REDUCE_PERCENTILE_95"
      case .reducePercentile50: return "REDUCE_PERCENTILE_50"
      case .reducePercentile05: return "REDUCE_PERCENTILE_05"
      case .reduceCountFalse: return "REDUCE_COUNT_FALSE"
      case .unknownIntValue: return nil
      case .unknownStringValue(let v): return v
      }
    }

    /// Initialize from a string value.
    ///
    /// If the value is unknown, this initializes to [`unknownStringValue`](doc:Reducer/unknownStringValue(_:)).
    public init(stringValue: Swift.String) {
      switch stringValue {
      case "REDUCE_NONE": self = .reduceNone
      case "REDUCE_MEAN": self = .reduceMean
      case "REDUCE_MIN": self = .reduceMin
      case "REDUCE_MAX": self = .reduceMax
      case "REDUCE_SUM": self = .reduceSum
      case "REDUCE_STDDEV": self = .reduceStddev
      case "REDUCE_COUNT": self = .reduceCount
      case "REDUCE_COUNT_TRUE": self = .reduceCountTrue
      case "REDUCE_COUNT_FALSE": self = .reduceCountFalse
      case "REDUCE_FRACTION_TRUE": self = .reduceFractionTrue
      case "REDUCE_PERCENTILE_99": self = .reducePercentile99
      case "REDUCE_PERCENTILE_95": self = .reducePercentile95
      case "REDUCE_PERCENTILE_50": self = .reducePercentile50
      case "REDUCE_PERCENTILE_05": self = .reducePercentile05
      default: self = .unknownStringValue(stringValue)
      }
    }

    /// Initialize from an integer value.
    ///
    /// If the value is unknown, this initializes to [`unknownIntValue`](doc:Reducer/unknownIntValue(_:)).
    public init(intValue: Int) {
      switch intValue {
      case 0: self = .reduceNone
      case 1: self = .reduceMean
      case 2: self = .reduceMin
      case 3: self = .reduceMax
      case 4: self = .reduceSum
      case 5: self = .reduceStddev
      case 6: self = .reduceCount
      case 7: self = .reduceCountTrue
      case 8: self = .reduceFractionTrue
      case 9: self = .reducePercentile99
      case 10: self = .reducePercentile95
      case 11: self = .reducePercentile50
      case 12: self = .reducePercentile05
      case 15: self = .reduceCountFalse
      default: self = .unknownIntValue(intValue)
      }
    }

    public init(from decoder: Decoder) throws {
      let container = try decoder.singleValueContainer()
      if let v = try? container.decode(Int.self) {
        self.init(intValue: v)
        return
      }
      if let s = try? container.decode(String.self) {
        if let v = Int(s) {
          self.init(intValue: v)
        } else {
          self.init(stringValue: s)
        }
        return
      }
      throw DecodingError.dataCorruptedError(
        in: container, debugDescription: "Expected enum value, must be integer or string.")
    }

    public func encode(to encoder: Encoder) throws {
      var container = encoder.singleValueContainer()
      switch self {
      case .reduceNone: return try container.encode(0)
      case .reduceMean: return try container.encode(1)
      case .reduceMin: return try container.encode(2)
      case .reduceMax: return try container.encode(3)
      case .reduceSum: return try container.encode(4)
      case .reduceStddev: return try container.encode(5)
      case .reduceCount: return try container.encode(6)
      case .reduceCountTrue: return try container.encode(7)
      case .reduceFractionTrue: return try container.encode(8)
      case .reducePercentile99: return try container.encode(9)
      case .reducePercentile95: return try container.encode(10)
      case .reducePercentile50: return try container.encode(11)
      case .reducePercentile05: return try container.encode(12)
      case .reduceCountFalse: return try container.encode(15)
      case .unknownIntValue(let v): return try container.encode(v)
      case .unknownStringValue(let v): return try container.encode(v)
      }
    }
  }

  public static var _anyTypeUrl: Swift.String {
    return "type.googleapis.com/google.monitoring.dashboard.v1.Aggregation"
  }
  public init(fromAny any: GoogleCloudWkt.`Any`) throws {
    self = try GoogleCloudWkt._slowAnyDeserialize(Self.self, from: any)
  }
  public func _pack() throws -> GoogleCloudWkt.Struct {
    return try GoogleCloudWkt._slowAnySerialize(message: self)
  }
}
