syntax = "proto3";
package transforms;

import "expression.proto";

// Filter
message Filter {
  expression.Expression expr = 1;
}

// Formula
message Formula {
  expression.Expression expr = 1;
  string as = 2;
}

// Extent
message Extent {
  string field = 1;
  optional string signal = 2;
}

// Collect
message Collect {
  repeated string fields = 1;
  repeated SortOrder order = 2;
}

enum SortOrder {
  Descending=0;
  Ascending=1;
}

// Bin
message Bin {
  string field = 1;
  expression.Expression extent = 2;
  optional string signal = 3;
  optional string alias_0 = 4;
  optional string alias_1 = 5;

  // A value in the binned domain at which to anchor the bins The bin boundaries will be shifted,
  // if necessary, to ensure that a boundary aligns with the anchor value.
  optional double anchor = 6;

  // The maximum number of bins allowed
  double maxbins = 7;

  // The number base to use for automatic bin selection (e.g. base 10)
  double base = 8;

  // An exact step size to use between bins. Overrides other options.
  optional double step = 9;

  // A list of allowable step sizes to choose from
  repeated double steps = 10;

  // The value span over which to generate bin boundaries. Defaults to the exact extent of the data
  expression.Expression span = 11;

  // A minimum distance between adjacent bins
  double minstep = 12;

  // Scale factors indicating the allowed subdivisions. The defualt value is vec![5.0, 2.0],
  // which indicates that for base 10 numbers, the method may consider dividing bin sizes by 5 and/or 2.
  repeated double divide = 13;

  // If true, attempt to make the bin boundaries use human-friendly boundaries
  // (e.g. whole numbers, multiples of 10, etc.)
  bool nice = 14;
}

// Aggregate
message Aggregate {
  repeated string groupby = 1;
  repeated string fields = 2;
  repeated string aliases = 3;
  repeated AggregateOp ops = 4;
}

enum AggregateOp {
    Count = 0;
    Valid = 1;
    Missing = 2;
    Distinct = 3;
    Sum = 4;
    Product = 5;
    Mean = 6;
    Average = 7;
    Variance = 8;
    Variancep = 9;
    Stdev = 10;
    Stdevp = 11;
    Stderr = 12;
    Median = 13;
    Q1 = 14;
    Q3 = 15;
    Ci0 = 16;
    Ci1 = 17;
    Min = 18;
    Max = 19;
    Argmin = 20;
    Argmax = 21;
    Values = 22;
}

// JoinAggregate
message JoinAggregate {
  repeated string groupby = 1;
  repeated string fields = 2;
  repeated AggregateOp ops = 3;
  repeated string aliases = 4;
}

// TimeUnit
message TimeUnit {
  string field = 1;
  repeated TimeUnitUnit units = 2;
  optional string signal = 3;
  optional string alias_0 = 4;
  optional string alias_1 = 5;
  optional TimeUnitTimeZone timezone = 6;
}


enum TimeUnitUnit {
  Year = 0;
  Quarter = 1;
  Month = 2;
  Date = 3;
  Week = 4;
  Day = 5;
  DayOfYear = 6;
  Hours = 7;
  Minutes = 8;
  Seconds = 9;
  Milliseconds = 10;
}

enum TimeUnitTimeZone {
  Local = 0;
  Utc = 1;
}


// Window
enum WindowOp {
  RowNumber = 0;
  Rank = 1;
  DenseRank = 2;
  PercentileRank = 3;
  CumeDist = 4;
  NTile = 5;
  Lag = 6;
  Lead = 7;
  FirstValue = 8;
  LastValue = 9;
  NthValue = 10;
  PrevValue = 11;
  NextValue = 12;
}

message WindowTransformOp {
  oneof op {
    AggregateOp aggregate_op = 1;
    WindowOp window_op = 2;
  }
}


message Window {
  repeated SortOrder sort = 1;
  repeated string sort_fields = 2;
  repeated string groupby = 3;
  repeated WindowTransformOp ops = 4;
  repeated string fields = 5;
  repeated double params = 6;
  repeated string aliases = 7;
  optional WindowFrame frame = 8;
  optional bool ignore_peers = 9;
}

message WindowFrame {
  optional int64 start = 1;
  optional int64 end = 2;
}

// Project
message Project {
  repeated string fields = 1;
}

// Stack
message Stack {
  string field = 1;
  StackOffset offset = 2;
  repeated SortOrder sort = 3;
  repeated string sort_fields = 4;
  repeated string groupby = 5;
  optional string alias_0 = 6;
  optional string alias_1 = 7;
}

enum StackOffset {
  Zero = 0;
  Center = 1;
  Normalize = 2;
}

// Impute
message Impute {
  string field = 1;
  string key = 2;
  ImputeMethod method = 3;
  repeated string groupby = 4;
  optional string value_json = 5;
}

enum ImputeMethod {
    ImputeValue = 0;
    ImputeMean = 1;
    ImputeMedian = 2;
    ImputeMax = 3;
    ImputeMin = 4;
}

// Pivot
message Pivot {
  string field = 1;
  string value = 2;
  repeated string groupby = 3;
  optional int32 limit = 4;
  optional AggregateOp op = 5;
}

// Identifier
message Identifier {
  string as = 1;
}

// Fold
message Fold {
  repeated string fields = 1;
  repeated string as = 2;
}

// Sequence
message Sequence {
  expression.Expression start = 1;
  expression.Expression stop = 2;
  optional expression.Expression step = 3;
  optional string as = 4;
}

// Top-level transform
message Transform {
  oneof transform_kind {
    Filter filter = 1;
    Extent extent = 2;
    Formula formula = 3;
    Bin bin = 4;
    Aggregate aggregate = 5;
    Collect collect = 6;
    TimeUnit timeunit = 7;
    JoinAggregate joinaggregate = 8;
    Window window = 9;
    Project project = 10;
    Stack stack = 11;
    Impute impute = 12;
    Pivot pivot = 13;
    Identifier identifier = 14;
    Fold fold = 15;
    Sequence sequence = 16;
  }
}

message TransformPipeline {
  repeated Transform transforms = 1;
}
