// Copyright 2024 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
//
//     http://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.

syntax = "proto3";

package google.analytics.admin.v1alpha;

import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/timestamp.proto";

option go_package = "cloud.google.com/go/analytics/admin/apiv1alpha/adminpb;adminpb";
option java_multiple_files = true;
option java_outer_classname = "AudienceProto";
option java_package = "com.google.analytics.admin.v1alpha";

// Specifies how to evaluate users for joining an Audience.
enum AudienceFilterScope {
  // Scope is not specified.
  AUDIENCE_FILTER_SCOPE_UNSPECIFIED = 0;

  // User joins the Audience if the filter condition is met within one
  // event.
  AUDIENCE_FILTER_SCOPE_WITHIN_SAME_EVENT = 1;

  // User joins the Audience if the filter condition is met within one
  // session.
  AUDIENCE_FILTER_SCOPE_WITHIN_SAME_SESSION = 2;

  // User joins the Audience if the filter condition is met by any event
  // across any session.
  AUDIENCE_FILTER_SCOPE_ACROSS_ALL_SESSIONS = 3;
}

// A specific filter for a single dimension or metric.
message AudienceDimensionOrMetricFilter {
  // A filter for a string-type dimension that matches a particular pattern.
  message StringFilter {
    // The match type for the string filter.
    enum MatchType {
      // Unspecified
      MATCH_TYPE_UNSPECIFIED = 0;

      // Exact match of the string value.
      EXACT = 1;

      // Begins with the string value.
      BEGINS_WITH = 2;

      // Ends with the string value.
      ENDS_WITH = 3;

      // Contains the string value.
      CONTAINS = 4;

      // Full regular expression matches with the string value.
      FULL_REGEXP = 5;
    }

    // Required. The match type for the string filter.
    MatchType match_type = 1 [(google.api.field_behavior) = REQUIRED];

    // Required. The string value to be matched against.
    string value = 2 [(google.api.field_behavior) = REQUIRED];

    // Optional. If true, the match is case-sensitive. If false, the match is
    // case-insensitive.
    bool case_sensitive = 3 [(google.api.field_behavior) = OPTIONAL];
  }

  // A filter for a string dimension that matches a particular list of options.
  message InListFilter {
    // Required. The list of possible string values to match against. Must be
    // non-empty.
    repeated string values = 1 [(google.api.field_behavior) = REQUIRED];

    // Optional. If true, the match is case-sensitive. If false, the match is
    // case-insensitive.
    bool case_sensitive = 2 [(google.api.field_behavior) = OPTIONAL];
  }

  // To represent a number.
  message NumericValue {
    // One of a numeric value.
    oneof one_value {
      // Integer value.
      int64 int64_value = 1;

      // Double value.
      double double_value = 2;
    }
  }

  // A filter for numeric or date values on a dimension or metric.
  message NumericFilter {
    // The operation applied to a numeric filter.
    enum Operation {
      // Unspecified.
      OPERATION_UNSPECIFIED = 0;

      // Equal.
      EQUAL = 1;

      // Less than.
      LESS_THAN = 2;

      // Greater than.
      GREATER_THAN = 4;
    }

    // Required. The operation applied to a numeric filter.
    Operation operation = 1 [(google.api.field_behavior) = REQUIRED];

    // Required. The numeric or date value to match against.
    NumericValue value = 2 [(google.api.field_behavior) = REQUIRED];
  }

  // A filter for numeric or date values between certain values on a dimension
  // or metric.
  message BetweenFilter {
    // Required. Begins with this number, inclusive.
    NumericValue from_value = 1 [(google.api.field_behavior) = REQUIRED];

    // Required. Ends with this number, inclusive.
    NumericValue to_value = 2 [(google.api.field_behavior) = REQUIRED];
  }

  // One of the above filters.
  oneof one_filter {
    // A filter for a string-type dimension that matches a particular pattern.
    StringFilter string_filter = 2;

    // A filter for a string dimension that matches a particular list of
    // options.
    InListFilter in_list_filter = 3;

    // A filter for numeric or date values on a dimension or metric.
    NumericFilter numeric_filter = 4;

    // A filter for numeric or date values between certain values on a dimension
    // or metric.
    BetweenFilter between_filter = 5;
  }

  // Required. Immutable. The dimension name or metric name to filter. If the
  // field name refers to a custom dimension or metric, a scope prefix will be
  // added to the front of the custom dimensions or metric name. For more on
  // scope prefixes or custom dimensions/metrics, reference the [Google
  // Analytics Data API documentation]
  // (https://developers.google.com/analytics/devguides/reporting/data/v1/api-schema#custom_dimensions).
  string field_name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.field_behavior) = IMMUTABLE
  ];

  // Optional. Indicates whether this filter needs dynamic evaluation or not. If
  // set to true, users join the Audience if they ever met the condition (static
  // evaluation). If unset or set to false, user evaluation for an Audience is
  // dynamic; users are added to an Audience when they meet the conditions and
  // then removed when they no longer meet them.
  //
  // This can only be set when Audience scope is ACROSS_ALL_SESSIONS.
  bool at_any_point_in_time = 6 [(google.api.field_behavior) = OPTIONAL];

  // Optional. If set, specifies the time window for which to evaluate data in
  // number of days. If not set, then audience data is evaluated against
  // lifetime data (For example, infinite time window).
  //
  // For example, if set to 1 day, only the current day's data is evaluated. The
  // reference point is the current day when at_any_point_in_time is unset or
  // false.
  //
  // It can only be set when Audience scope is ACROSS_ALL_SESSIONS and cannot be
  // greater than 60 days.
  int32 in_any_n_day_period = 7 [(google.api.field_behavior) = OPTIONAL];
}

// A filter that matches events of a single event name. If an event parameter
// is specified, only the subset of events that match both the single event name
// and the parameter filter expressions match this event filter.
message AudienceEventFilter {
  // Required. Immutable. The name of the event to match against.
  string event_name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.field_behavior) = IMMUTABLE
  ];

  // Optional. If specified, this filter matches events that match both the
  // single event name and the parameter filter expressions. AudienceEventFilter
  // inside the parameter filter expression cannot be set (For example, nested
  // event filters are not supported). This should be a single and_group of
  // dimension_or_metric_filter or not_expression; ANDs of ORs are not
  // supported. Also, if it includes a filter for "eventCount", only that one
  // will be considered; all the other filters will be ignored.
  AudienceFilterExpression event_parameter_filter_expression = 2
      [(google.api.field_behavior) = OPTIONAL];
}

// A logical expression of Audience dimension, metric, or event filters.
message AudienceFilterExpression {
  // The expression applied to a filter.
  oneof expr {
    // A list of expressions to be AND’ed together. It can only contain
    // AudienceFilterExpressions with or_group. This must be set for the top
    // level AudienceFilterExpression.
    AudienceFilterExpressionList and_group = 1;

    // A list of expressions to OR’ed together. It cannot contain
    // AudienceFilterExpressions with and_group or or_group.
    AudienceFilterExpressionList or_group = 2;

    // A filter expression to be NOT'ed (For example, inverted, complemented).
    // It can only include a dimension_or_metric_filter. This cannot be set on
    // the top level AudienceFilterExpression.
    AudienceFilterExpression not_expression = 3;

    // A filter on a single dimension or metric. This cannot be set on the top
    // level AudienceFilterExpression.
    AudienceDimensionOrMetricFilter dimension_or_metric_filter = 4;

    // Creates a filter that matches a specific event. This cannot be set on the
    // top level AudienceFilterExpression.
    AudienceEventFilter event_filter = 5;
  }
}

// A list of Audience filter expressions.
message AudienceFilterExpressionList {
  // A list of Audience filter expressions.
  repeated AudienceFilterExpression filter_expressions = 1;
}

// Defines a simple filter that a user must satisfy to be a member of the
// Audience.
message AudienceSimpleFilter {
  // Required. Immutable. Specifies the scope for this filter.
  AudienceFilterScope scope = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.field_behavior) = IMMUTABLE
  ];

  // Required. Immutable. A logical expression of Audience dimension, metric, or
  // event filters.
  AudienceFilterExpression filter_expression = 2 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.field_behavior) = IMMUTABLE
  ];
}

// Defines filters that must occur in a specific order for the user to be a
// member of the Audience.
message AudienceSequenceFilter {
  // A condition that must occur in the specified step order for this user
  // to match the sequence.
  message AudienceSequenceStep {
    // Required. Immutable. Specifies the scope for this step.
    AudienceFilterScope scope = 1 [
      (google.api.field_behavior) = REQUIRED,
      (google.api.field_behavior) = IMMUTABLE
    ];

    // Optional. If true, the event satisfying this step must be the very next
    // event after the event satisfying the last step. If unset or false, this
    // step indirectly follows the prior step; for example, there may be
    // events between the prior step and this step. It is ignored for the
    // first step.
    bool immediately_follows = 2 [(google.api.field_behavior) = OPTIONAL];

    // Optional. When set, this step must be satisfied within the
    // constraint_duration of the previous step (For example,  t[i] - t[i-1] <=
    // constraint_duration). If not set, there is no duration requirement (the
    // duration is effectively unlimited). It is ignored for the first step.
    google.protobuf.Duration constraint_duration = 3
        [(google.api.field_behavior) = OPTIONAL];

    // Required. Immutable. A logical expression of Audience dimension, metric,
    // or event filters in each step.
    AudienceFilterExpression filter_expression = 4 [
      (google.api.field_behavior) = REQUIRED,
      (google.api.field_behavior) = IMMUTABLE
    ];
  }

  // Required. Immutable. Specifies the scope for this filter.
  AudienceFilterScope scope = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.field_behavior) = IMMUTABLE
  ];

  // Optional. Defines the time period in which the whole sequence must occur.
  google.protobuf.Duration sequence_maximum_duration = 2
      [(google.api.field_behavior) = OPTIONAL];

  // Required. An ordered sequence of steps. A user must complete each step in
  // order to join the sequence filter.
  repeated AudienceSequenceStep sequence_steps = 3
      [(google.api.field_behavior) = REQUIRED];
}

// A clause for defining either a simple or sequence filter. A filter can be
// inclusive (For example, users satisfying the filter clause are included in
// the Audience) or exclusive (For example, users satisfying the filter clause
// are excluded from the Audience).
message AudienceFilterClause {
  // Specifies whether this is an include or exclude filter clause.
  enum AudienceClauseType {
    // Unspecified clause type.
    AUDIENCE_CLAUSE_TYPE_UNSPECIFIED = 0;

    // Users will be included in the Audience if the filter clause is met.
    INCLUDE = 1;

    // Users will be excluded from the Audience if the filter clause is met.
    EXCLUDE = 2;
  }

  oneof filter {
    // A simple filter that a user must satisfy to be a member of the Audience.
    AudienceSimpleFilter simple_filter = 2;

    // Filters that must occur in a specific order for the user to be a member
    // of the Audience.
    AudienceSequenceFilter sequence_filter = 3;
  }

  // Required. Specifies whether this is an include or exclude filter clause.
  AudienceClauseType clause_type = 1 [(google.api.field_behavior) = REQUIRED];
}

// Specifies an event to log when a user joins the Audience.
message AudienceEventTrigger {
  // Determines when to log the event.
  enum LogCondition {
    // Log condition is not specified.
    LOG_CONDITION_UNSPECIFIED = 0;

    // The event should be logged only when a user is joined.
    AUDIENCE_JOINED = 1;

    // The event should be logged whenever the Audience condition is met, even
    // if the user is already a member of the Audience.
    AUDIENCE_MEMBERSHIP_RENEWED = 2;
  }

  // Required. The event name that will be logged.
  string event_name = 1 [(google.api.field_behavior) = REQUIRED];

  // Required. When to log the event.
  LogCondition log_condition = 2 [(google.api.field_behavior) = REQUIRED];
}

// A resource message representing a GA4 Audience.
message Audience {
  option (google.api.resource) = {
    type: "analyticsadmin.googleapis.com/Audience"
    pattern: "properties/{property}/audiences/{audience}"
  };

  // Specifies how long an exclusion lasts for users that meet the exclusion
  // filter.
  enum AudienceExclusionDurationMode {
    // Not specified.
    AUDIENCE_EXCLUSION_DURATION_MODE_UNSPECIFIED = 0;

    // Exclude users from the Audience during periods when they meet the
    // filter clause.
    EXCLUDE_TEMPORARILY = 1;

    // Exclude users from the Audience if they've ever met the filter clause.
    EXCLUDE_PERMANENTLY = 2;
  }

  // Output only. The resource name for this Audience resource.
  // Format: properties/{propertyId}/audiences/{audienceId}
  string name = 1 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Required. The display name of the Audience.
  string display_name = 2 [(google.api.field_behavior) = REQUIRED];

  // Required. The description of the Audience.
  string description = 3 [(google.api.field_behavior) = REQUIRED];

  // Required. Immutable. The duration a user should stay in an Audience. It
  // cannot be set to more than 540 days.
  int32 membership_duration_days = 4 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.field_behavior) = IMMUTABLE
  ];

  // Output only. It is automatically set by GA to false if this is an NPA
  // Audience and is excluded from ads personalization.
  bool ads_personalization_enabled = 5
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Optional. Specifies an event to log when a user joins the Audience. If not
  // set, no event is logged when a user joins the Audience.
  AudienceEventTrigger event_trigger = 6
      [(google.api.field_behavior) = OPTIONAL];

  // Immutable. Specifies how long an exclusion lasts for users that meet the
  // exclusion filter. It is applied to all EXCLUDE filter clauses and is
  // ignored when there is no EXCLUDE filter clause in the Audience.
  AudienceExclusionDurationMode exclusion_duration_mode = 7
      [(google.api.field_behavior) = IMMUTABLE];

  // Required. Immutable. Unordered list. Filter clauses that define the
  // Audience. All clauses will be AND’ed together.
  repeated AudienceFilterClause filter_clauses = 8 [
    (google.api.field_behavior) = IMMUTABLE,
    (google.api.field_behavior) = REQUIRED,
    (google.api.field_behavior) = UNORDERED_LIST
  ];

  // Output only. Time when the Audience was created.
  google.protobuf.Timestamp create_time = 9
      [(google.api.field_behavior) = OUTPUT_ONLY];
}
