syntax = "proto3";

package nominal.ingest.v2;

import "buf/validate/validate.proto";
import "nominal/protos/gen/v1/alias.proto";
import "nominal/protos/ingest/v2/common.proto";

option java_multiple_files = true;
option java_package = "io.nominal.ingest.v2";

// Direct file ingest work.
message FileIngestItem {
  IngestSource source = 1 [(buf.validate.field).required = true];
  FileIngestOptions ingest = 2 [(buf.validate.field).required = true];
}

// Direct file ingest mode.
message FileIngestOptions {
  TimestampMetadata timestamp_metadata = 1 [(buf.validate.field).required = true];
  map<string, string> units = 2 [(nominal.gen.v1.alias) = {
    key_java_name: "io.nominal.api.Channel"
    value_java_name: "io.nominal.api.Unit"
  }];
  optional string channel_prefix = 3;
  // Renames individual columns to explicit channel names. Composes with channel_prefix:
  // final name = channel_prefix + channel_name_overrides.getOrDefault(column, column).
  // At most 1000 entries may be provided. Resolved channel names must be unique across columns;
  // renaming a column onto another column's name fails the ingest.
  map<string, string> channel_name_overrides = 7 [(nominal.gen.v1.alias) = {
    key_java_name: "io.nominal.api.ColumnName"
    value_java_name: "io.nominal.api.Channel"
  }];

  oneof ingest {
    option (buf.validate.oneof) = {required: true};

    CsvIngestOptions csv = 4;
    ParquetIngestOptions parquet = 5;
    AvroIngestOptions avro = 6;
  }
}

// CSV ingest options.
message CsvIngestOptions {
  CsvFormat format = 1 [(buf.validate.field).required = true];
}

// Parquet ingest options.
message ParquetIngestOptions {
  ParquetFormat format = 1 [(buf.validate.field).required = true];
  bool is_archive = 2;
}

// Avro ingest options.
message AvroIngestOptions {}

message CsvFormat {
  oneof format {
    option (buf.validate.oneof) = {required: true};

    WideFormat wide = 1;
    LongFormat long = 2;
  }
}

message ParquetFormat {
  oneof format {
    option (buf.validate.oneof) = {required: true};

    WideFormat wide = 1;
    LongFormat long = 2;
  }
}

// Wide format: each row or record contains one timestamp and many channels as columns.
message WideFormat {
  map<string, string> tag_columns = 1 [(nominal.gen.v1.alias) = {
    key_java_name: "io.nominal.api.TagName"
    value_java_name: "io.nominal.api.ColumnName"
  }];
  repeated string exclude_columns = 2 [(nominal.gen.v1.alias) = {java_name: "io.nominal.api.ColumnName"}];
}

// Long format: each row or record contains one channel, timestamp, and value sample.
message LongFormat {
  // Defaults to "channel".
  optional string channel_column = 1 [(nominal.gen.v1.alias) = {java_name: "io.nominal.api.ColumnName"}];
  // Defaults to "value".
  optional string value_column = 2 [(nominal.gen.v1.alias) = {java_name: "io.nominal.api.ColumnName"}];
  // Defaults to "tags".
  optional string tags_column = 3 [(nominal.gen.v1.alias) = {java_name: "io.nominal.api.ColumnName"}];
}
