/********************************************************************************
 * Copyright (c) 2022 Contributors to the Eclipse Foundation
 *
 * See the NOTICE file(s) distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Apache License 2.0 which is available at
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * SPDX-License-Identifier: Apache-2.0
 ********************************************************************************/

syntax = "proto3";

// I added V1 as in databroker. Is this good practice?
package kuksa.val.v1;
import "google/protobuf/timestamp.proto";

option go_package = "kuksa/val/v1";

// Describes a VSS entry
// When requesting an entry, the amount of information returned can
// be controlled by specifying either a `View` or a set of `Field`s.
message DataEntry {
  // Defines the full VSS path of the entry.
  string path = 1;  // [field: FIELD_PATH]

  // The value (datapoint)
  Datapoint value = 2;  // [field: FIELD_VALUE]

  // Actuator target (only used if the entry is an actuator)
  Datapoint actuator_target = 3;  // [field: FIELD_ACTUATOR_TARGET]

  // Metadata for this entry
  Metadata metadata = 10;  // [field: FIELD_METADATA]
}

message Datapoint {
  google.protobuf.Timestamp timestamp = 1;

  oneof value {
    string string            = 11;
    bool bool                = 12;
    sint32 int32             = 13;
    sint64 int64             = 14;
    uint32 uint32            = 15;
    uint64 uint64            = 16;
    float float              = 17;
    double double            = 18;
    StringArray string_array = 21;
    BoolArray bool_array     = 22;
    Int32Array int32_array   = 23;
    Int64Array int64_array   = 24;
    Uint32Array uint32_array = 25;
    Uint64Array uint64_array = 26;
    FloatArray float_array   = 27;
    DoubleArray double_array = 28;
  }
}

message Metadata {
  // Data type
  // The VSS data type of the entry (i.e. the value, min, max etc).
  //
  // NOTE: protobuf doesn't have int8, int16, uint8 or uint16 which means
  // that these values must be serialized as int32 and uint32 respectively.
  DataType data_type = 11;  // [field: FIELD_METADATA_DATA_TYPE]

  // Entry type
  EntryType entry_type = 12;  // [field: FIELD_METADATA_ENTRY_TYPE]

  // Description
  // Describes the meaning and content of the entry.
  optional string description = 13;  // [field: FIELD_METADATA_DESCRIPTION]

  // Comment [optional]
  // A comment can be used to provide additional informal information
  // on a entry.
  optional string comment = 14;  // [field: FIELD_METADATA_COMMENT]

  // Deprecation [optional]
  // Whether this entry is deprecated. Can contain recommendations of what
  // to use instead.
  optional string deprecation = 15;  // [field: FIELD_METADATA_DEPRECATION]

  // Unit [optional]
  // The unit of measurement
  optional string unit = 16;  // [field: FIELD_METADATA_UNIT]

  // Value restrictions [optional]
  // Restrict which values are allowed.
  // Only restrictions matching the DataType {datatype} above are valid.
  ValueRestriction value_restriction = 17;  // [field: FIELD_METADATA_VALUE_RESTRICTION]

  // Entry type specific metadata
  oneof entry_specific {
    Actuator actuator   = 20;  // [field: FIELD_METADATA_ACTUATOR]
    Sensor sensor       = 30;  // [field: FIELD_METADATA_SENSOR]
    Attribute attribute = 40;  // [field: FIELD_METADATA_ATTRIBUTE]
  }
}

///////////////////////
// Actuator specific fields
message Actuator {
  // Nothing for now
}

////////////////////////
// Sensor specific
message Sensor {
  // Nothing for now
}

////////////////////////
// Attribute specific
message Attribute {
  // Nothing for now.
}

// Value restriction
//
// One ValueRestriction{type} for each type, since
// they don't make sense unless the types match
//
message ValueRestriction {
  oneof type {
    ValueRestrictionString string = 21;
    // For signed VSS integers
    ValueRestrictionInt signed = 22;
    // For unsigned VSS integers
    ValueRestrictionUint unsigned = 23;
    // For floating point VSS values (float and double)
    ValueRestrictionFloat floating_point = 24;
  }
}

message ValueRestrictionInt {
  optional sint64 min            = 1;
  optional sint64 max            = 2;
  repeated sint64 allowed_values = 3;
}

message ValueRestrictionUint {
  optional uint64 min            = 1;
  optional uint64 max            = 2;
  repeated uint64 allowed_values = 3;
}

message ValueRestrictionFloat {
  optional double min = 1;
  optional double max = 2;

  // allowed for doubles/floats not recommended
  repeated double allowed_values = 3;
}

// min, max doesn't make much sense for a string
message ValueRestrictionString {
  repeated string allowed_values = 3;
}

// VSS Data type of a signal
//
// Protobuf doesn't support int8, int16, uint8 or uint16.
// These are mapped to int32 and uint32 respectively.
//
enum DataType {
  DATA_TYPE_UNSPECIFIED     = 0;
  DATA_TYPE_STRING          = 1;
  DATA_TYPE_BOOLEAN         = 2;
  DATA_TYPE_INT8            = 3;
  DATA_TYPE_INT16           = 4;
  DATA_TYPE_INT32           = 5;
  DATA_TYPE_INT64           = 6;
  DATA_TYPE_UINT8           = 7;
  DATA_TYPE_UINT16          = 8;
  DATA_TYPE_UINT32          = 9;
  DATA_TYPE_UINT64          = 10;
  DATA_TYPE_FLOAT           = 11;
  DATA_TYPE_DOUBLE          = 12;
  DATA_TYPE_TIMESTAMP       = 13;
  DATA_TYPE_STRING_ARRAY    = 20;
  DATA_TYPE_BOOLEAN_ARRAY   = 21;
  DATA_TYPE_INT8_ARRAY      = 22;
  DATA_TYPE_INT16_ARRAY     = 23;
  DATA_TYPE_INT32_ARRAY     = 24;
  DATA_TYPE_INT64_ARRAY     = 25;
  DATA_TYPE_UINT8_ARRAY     = 26;
  DATA_TYPE_UINT16_ARRAY    = 27;
  DATA_TYPE_UINT32_ARRAY    = 28;
  DATA_TYPE_UINT64_ARRAY    = 29;
  DATA_TYPE_FLOAT_ARRAY     = 30;
  DATA_TYPE_DOUBLE_ARRAY    = 31;
  DATA_TYPE_TIMESTAMP_ARRAY = 32;
}

// Entry type
enum EntryType {
  ENTRY_TYPE_UNSPECIFIED = 0;
  ENTRY_TYPE_ATTRIBUTE   = 1;
  ENTRY_TYPE_SENSOR      = 2;
  ENTRY_TYPE_ACTUATOR    = 3;
}

// A `View` specifies a set of fields which should
// be populated in a `DataEntry` (in a response message)
enum View {
  VIEW_UNSPECIFIED   = 0;   // Unspecified. Equivalent to VIEW_CURRENT_VALUE unless `fields` are explicitly set.
  VIEW_CURRENT_VALUE = 1;   // Populate DataEntry with value.
  VIEW_TARGET_VALUE  = 2;   // Populate DataEntry with actuator target.
  VIEW_METADATA      = 3;   // Populate DataEntry with metadata.
  VIEW_FIELDS        = 10;  // Populate DataEntry only with requested fields.
  VIEW_ALL           = 20;  // Populate DataEntry with everything.
}

// A `Field` corresponds to a specific field of a `DataEntry`.
//
// It can be used to:
//   * populate only specific fields of a `DataEntry` response.
//   * specify which fields of a `DataEntry` should be set as
//     part of a `Set` request.
//   * subscribe to only specific fields of a data entry.
//   * convey which fields of an updated `DataEntry` have changed.
enum Field {
  FIELD_UNSPECIFIED                = 0;   // "*" i.e. everything
  FIELD_PATH                       = 1;   // path
  FIELD_VALUE                      = 2;   // value
  FIELD_ACTUATOR_TARGET            = 3;   // actuator_target
  FIELD_METADATA                   = 10;  // metadata.*
  FIELD_METADATA_DATA_TYPE         = 11;  // metadata.data_type
  FIELD_METADATA_DESCRIPTION       = 12;  // metadata.description
  FIELD_METADATA_ENTRY_TYPE        = 13;  // metadata.entry_type
  FIELD_METADATA_COMMENT           = 14;  // metadata.comment
  FIELD_METADATA_DEPRECATION       = 15;  // metadata.deprecation
  FIELD_METADATA_UNIT              = 16;  // metadata.unit
  FIELD_METADATA_VALUE_RESTRICTION = 17;  // metadata.value_restriction.*
  FIELD_METADATA_ACTUATOR          = 20;  // metadata.actuator.*
  FIELD_METADATA_SENSOR            = 30;  // metadata.sensor.*
  FIELD_METADATA_ATTRIBUTE         = 40;  // metadata.attribute.*
}

// Error response shall be an HTTP-like code.
// Should follow https://www.w3.org/TR/viss2-transport/#status-codes.
message Error {
  uint32 code    = 1;
  string reason  = 2;
  string message = 3;
}

// Used in get/set requests to report errors for specific entries
message DataEntryError {
  string path = 1;  // vss path
  Error error = 2;
}

message StringArray {
  repeated string values = 1;
}

message BoolArray {
  repeated bool values = 1;
}

message Int32Array {
  repeated sint32 values = 1;
}

message Int64Array {
  repeated sint64 values = 1;
}

message Uint32Array {
  repeated uint32 values = 1;
}

message Uint64Array {
  repeated uint64 values = 1;
}

message FloatArray {
  repeated float values = 1;
}

message DoubleArray {
  repeated double values = 1;
}
