syntax = "proto3";
package confidence.flags.types.v1;

import "google/protobuf/timestamp.proto";

option go_package = "github.com/spotify/confidence-resolver/openfeature-provider/go/confidence/internal/proto/types";
option java_multiple_files = true;
option java_package = "com.spotify.confidence.flags.types.v1";
option java_outer_classname = "TargetingProto";


message Targeting {
  map<string, Criterion> criteria = 1;
  Expression expression = 2;

  message Criterion {
    oneof criterion {
      AttributeCriterion attribute = 1;
      SegmentCriterion segment = 2 ;
      MaterializedSegmentCriterion materialized_segment = 3;
    }
    message AttributeCriterion {
      string attribute_name = 1;

      oneof rule {
        EqRule eq_rule = 2;
        SetRule set_rule = 3;
        RangeRule range_rule = 4;
        AnyRule any_rule = 5;
        AllRule all_rule = 6;
        StartsWithRule starts_with_rule = 7;
        EndsWithRule ends_with_rule = 8;
      }
    }

    message SegmentCriterion {
      string segment = 1;
    }

    message MaterializedSegmentCriterion {
      string materialized_segment = 1;
    }
  }

  // is match if at least one input item matches the inner rule
  // is not match if the input list is empty/missing
  message AnyRule {
    InnerRule rule = 1;
  }

  // is match if each and every input item matches the inner rule
  // is also match if the input field is empty/missing
  message AllRule {
    InnerRule rule = 1;
  }

  message InnerRule {
    oneof rule {
      EqRule eq_rule = 1;
      SetRule set_rule = 2;
      RangeRule range_rule = 3;
      StartsWithRule starts_with_rule = 4;
      EndsWithRule ends_with_rule = 5;
    }
  }

  // same as SetRule with a single value
  message EqRule {
    Value value = 1;
  }

  // represents a set of allowed values
  // in {a, b, c}  -> x == a || x == b || x == c || ...
  // not in {a, b} -> x != a && x != b && ...
  message SetRule {
    repeated Value values = 1;
  }

  // represents a criteria on a value using inequalities
  // closed range start, end -> start <[=] x && x <[=] end
  // open end start, ...     -> start <[=] x
  // open start ..., end     -> x <[=] end
  message RangeRule {
    oneof start {
      Value start_inclusive = 1;
      Value start_exclusive = 2;
    }
    oneof end {
      Value end_inclusive = 3;
      Value end_exclusive = 4;
    }
  }

  // matches if the string value starts with the given prefix
  message StartsWithRule {
    string value = 1;
  }

  // matches if the string value ends with the given suffix
  message EndsWithRule {
    string value = 1;
  }

  // equality (==, !=, ∈) defined for all types
  // comparison (<, <=, >, >=) defined for number, timestamp, version
  message Value {
    oneof value {
      bool bool_value = 1;
      double number_value = 7;
      string string_value = 4;
      google.protobuf.Timestamp timestamp_value = 5;
      SemanticVersion version_value = 6;
      ListValue list_value = 8;
    }
  }

  message ListValue {
    repeated Value values = 1;
  }

  message SemanticVersion {
    string version = 1;
  }
}

// A boolean expression with leaf nodes that reference criteria elements
message Expression {
  oneof expression {
    string ref = 1;
    Expression not = 2;
    Operands and = 3;
    Operands or = 4;
  }

  message Operands {
    repeated Expression operands = 1;
  }
}
