// "cdm index" for grib collections, using ncx4 suffix

syntax = "proto3";
option java_package = "ucar.nc2.grib.collection";
option java_outer_classname = "GribCollectionProto";

message Record {
  uint32 fileno = 1;               // which GRIB file ? key into GC.fileMap
  uint64 startPos = 2;             // offset in GRIB file of the start of entire message
  uint32 bmsOffset = 3;            // use alternate bms if non-zero (grib2 only). offset from start
  uint32 drsOffset = 4;            // offset of drs from start (grib2 only)
}

// SparseArray only at the GCs (MRC and SRC) not at the Partitions
// dont need SparseArray in memory until someone wants to read from the variable
message SparseArray {
  repeated uint32 size = 2 [packed=true];     // multidim sizes = shape[]
  repeated uint32 track = 3 [packed=true];    // 1-based index into record list, 0 == missing
  repeated Record records = 4;                // List<Record>
  uint32 ndups = 5;                           // duplicates found when creating
}

///////////////////////////////////////////////////////////////////////////

message Variable {
   uint32 discipline = 1;
   bytes pds = 2;                   // raw pds
   repeated uint32 ids = 3 [packed=true];         // extra info not in pds; grib2 id section

   uint64 recordsPos = 4;  // offset of SparseArray message for this Variable
   uint32 recordsLen = 5;  // size of SparseArray message for this Variable

   repeated uint32 coordIdx = 6 [packed=true];    // indexes into Group.coords

   // optionally keep stats
   uint32 ndups = 8;
   uint32 nrecords = 9;
   uint32 missing = 10;

   // partition only
   repeated PartitionVariable partVariable = 100;
 }

 enum GribAxisType {  // same as ucar.coord.Coordinate.Type
    runtime=0;
    time=1;
    timeIntv=2;
    vert=3;
    time2D=4;
    ens=5;
 }

message Coord {
  GribAxisType axisType = 1;
  int32 code = 2;   // time unit; level type
  string unit = 3;
  repeated float values = 4 [packed=true];
  repeated float bound = 5 [packed=true]; // only used if interval, then = (value, bound)
  repeated int64 msecs = 6 [packed=true]; // calendar date : runtime, time2D

  repeated Coord times = 7; // time2D only
  bool isOrthogonal = 8; // time2D only
  bool isRegular = 9; // time2D only

  repeated uint32 time2runtime = 10 [packed=true];  // time index to runtime index, Best Time only
}

message Parameter {
  string name = 1;
  repeated double data = 2;
  string sdata = 3; // used for string data
}

message Gds {
  bytes gds = 1;                        // raw gds: Grib1SectionGridDefinition or Grib2SectionGridDefinition
  uint32 predefinedGridDefinition = 2;  // only grib1; instead of gds raw bytes; need center, subcenter to interpret
}

message Group {
  Gds gds = 1;                             // use this to build the HorizCoordSys
  repeated Variable variables = 2;         // list of variables
  repeated Coord coords = 3;               // list of coordinates
  repeated uint32 fileno = 4 [packed=true]; // the component files that are in this group, key into gc.mfiles
}

message Dataset {
  enum Type {
    GC = 0;         // leaf collection
    SRC = 4;        // single runtime collection
    MRC = 5;        // multiple runtime collection
    MRSTC = 6;      // multiple runtime single time collection
    MRUTC = 8;      // Multiple Runtime Unique Time Collection

    MRSTP = 7;      // multiple runtime single time partition
    TwoD = 1;       // time partition 2D
    Best = 2;       // time partition Best
    MRUTP = 9;      // Multiple Runtime Unique Time Partition
  }

  Type type = 1;
  repeated Group groups = 2;
}

message MFile {
  string filename = 1;           // relative to topDir
  uint64 lastModified = 2;
  uint32 index = 3;             // the records use this number
  uint64 length = 4;
}

message GribCollection {
  string name = 1;         // must be unique - index filename is name.ncx
  string topDir = 2;       // MFile, Partition filenames are relative to this
  repeated MFile mfiles = 3;        // list of grib MFiles
  repeated Dataset dataset = 4;
  repeated Gds gds = 5;             // unique Gds, shared amongst datasets
  Coord masterRuntime = 6;  // list of runtimes in this GC

  // LOOK these are taken from first record; not storing variants (!)
  int32 center = 7;      // these 4 fields are to get a GribCustomizer
  int32 subcenter = 8;
  int32 master = 9;
  int32 local = 10;       // grib1 table Version

  int32 genProcessType = 11;
  int32 genProcessId = 12;
  int32 backProcessId = 13;
  int32 version = 14;     // >= 3 for proto3 (5.0+)

  // repeated Parameter params = 20;      // not used
  FcConfig config = 21;
  uint64 startTime = 22; // calendar date, first valid time
  uint64 endTime = 23;   // calendar date, last valid time

  // extensions
  repeated Partition partitions = 100;
  bool isPartitionOfPartitions = 101;
  repeated uint32 run2part = 102 [packed=true];  // masterRuntime index to partition index
}

/////////////////////////
// partition only

message PartitionVariable {
  uint32 groupno = 1;
  uint32 varno = 2;
  uint32 partno = 4;

  // optionally keep stats
  uint32 ndups = 8;
  uint32 nrecords = 9;
  uint32 missing = 10;
}

message Partition {
  string name = 1;       // name is used in TDS - eg the subdirectory when generated by TimePartitionCollections
  string filename = 2;   // the gribCollection.ncx file, relative to gc.
  uint64 lastModified = 4;
  int64 length = 5;
  int64 partitionDate = 6;  // partition date added 11/25/14
}

//////////////////////////
// configuration not really used

message StringMap {
  string name = 1;
  string value = 2;
}

message IntMap {
  sint32 from = 1;
  sint32 to = 2;
}

message IntvFilter {
  sint32 intvLength = 1;
  uint32 variableId = 2;
  sint32 intvProb = 3;
}

// apparently not used
message FcConfig {
  string name = 1;
  string collectionSpec = 2;
  string partitionType = 3;
  string dateFormatMark = 4;

  repeated IntMap gdsConvert = 11;
  bool pdsUseGenType = 12;
  bool pdsUseTableVersion = 13; // [default = true];
  bool pdsIntvMerge = 14; // [default = true];
  bool pdsUseCenter = 15; // [default = true];
  bool intvExcludeZero = 16;
  repeated IntvFilter intvFilter = 17;
  repeated IntMap timeUnitConvert = 18;
  string userTimeUnit = 19;
}

//  cd netcdf-java/grib/src/main/java
//  protoc --proto_path=. --java_out=. ucar/nc2/grib/collection/gribCollection4.proto