/*
  Сервис работы с камерами
*/
syntax = "proto3";
package keyapis.vc.v1;
import "google/api/annotations.proto";
import "google/api/field_behavior.proto";
import "google/protobuf/descriptor.proto";
import "google/protobuf/wrappers.proto";
import "google/protobuf/timestamp.proto";

option cc_enable_arenas = true;
option csharp_namespace = "Keyapis.Vc.V1";
option go_package = "/keyapis_vc_v1";
option java_multiple_files = false;
option java_outer_classname = "KeyapisVcV1Proto";
option java_package = "ru.keyapis.vc.v1";
option java_string_check_utf8 = true;
option objc_class_prefix = "KEYAPISVCV1";
option optimize_for = LITE_RUNTIME;
option php_namespace = "Keyapis\\Vc\\V1";
option ruby_package = "Keyapis::Vc::V1";

// Сервис работы с камерами
service CameraService {
  // Метод получения количества связей камеры и квартиры.
  // Метод доступен для: admin, service, bti, owner, employee
  rpc GetCameraRoomCount ( GetCameraRoomCountRequest ) returns ( GetCameraRoomCountResponse ) {
    option (google.api.http) = { get: "/vc/api/v1/camera/room/count" };
  }
  // Метод получения списка связей камеры и квартиры.
  // Метод доступен для: admin, service, bti, owner, employee
  rpc GetCameraRoomList ( GetCameraRoomListRequest ) returns ( stream GetCameraRoomListResponse ) {
    option (google.api.http) = { get: "/vc/api/v1/camera/room/list" };
  }
  // Метод получения камеры.
  // Для owner, employee параметр scope.vc_company_id подставляется из токена.
  // Метод доступен для: admin, service, bti, ltp_first, owner, employee
  rpc GetCamera ( GetCameraRequest ) returns ( GetCameraResponse ) {
    option (google.api.http) = { get: "/vc/api/v1/camera/{uid}" };
  }
  // Метод получения списка камер.
  // Для owner, employee параметр scope.vc_company_id подставляется из токена.
  // Метод доступен для: admin, service, bti, ltp_first, owner, employee
  rpc GetCameraList ( GetCameraListRequest ) returns ( GetCameraListResponse ) {
    option (google.api.http) = { get: "/vc/api/v1/camera/list" };
  }
  // Метод получения RTSP-ссылки по идентификатору камеры в vcfront.
  // Метод доступен для: admin, service.
  // Метод доступен для: ApiKey
  rpc GetCameraRtspUrlExternalId ( GetCameraRtspUrlExternalIdRequest ) returns ( GetCameraRtspUrlExternalIdResponse ) {
    option (google.api.http) = {
      get: "/vc/api/v1/camera/rtsp_url/external_id/{external_id}"
    };
  }
  // Метод привязки камеры и квартиры.
  // Метод доступен для: admin, service, bti, owner, employee
  rpc PutCameraRoomAttach ( PutCameraRoomAttachRequest ) returns ( PutCameraRoomAttachResponse ) {
    option (google.api.http) = {
      put: "/vc/api/v1/camera/{data.camera_uid}/room/{data.orpon}/{data.room_number}/attach"
    };
  }
  // Метод отвязки камеры и квартиры.
  // Метод доступен для: admin, service, bti, owner, employee
  rpc PutCameraRoomDetach ( PutCameraRoomDetachRequest ) returns ( PutCameraRoomDetachResponse ) {
    option (google.api.http) = {
      put: "/vc/api/v1/camera/{data.camera_uid}/room/{data.orpon}/{data.room_number}/detach"
    };
  }
  // Метод пакетной привязки камер и квартир.
  // Метод доступен для: admin, service, bti, owner, employee
  rpc PutCameraRoomAttachList ( PutCameraRoomAttachListRequest ) returns ( PutCameraRoomAttachListResponse ) {
    option (google.api.http) = {
      put: "/vc/api/v1/camera/room/attach/list",
      body: "*"
    };
  }
  // Метод пакетной отвязки камер и квартир.
  // Метод доступен для: admin, service, bti, owner, employee
  rpc PutCameraRoomDetachList ( PutCameraRoomDetachListRequest ) returns ( PutCameraRoomDetachListResponse ) {
    option (google.api.http) = {
      put: "/vc/api/v1/camera/room/detach/list",
      body: "*"
    };
  }
  // Метод удаления камеры.
  // Метод доступен для: admin, service, bti
  rpc DeleteCamera(DeleteCameraRequest) returns (DeleteCameraResponse) {
    option (google.api.http) = {
      delete: "/vc/api/v1/camera/{uid}"
    };
  }
  // Метод создания камеры.
  // Метод доступен для: admin, service, bti
  rpc PostCamera(PostCameraRequest) returns (PostCameraResponse) {
    option (google.api.http) = {
      post: "/vc/api/v1/camera",
      body: "*"
    };
  }
  // Метод получения дней, когда доступны записи.
  // Метод доступен для: admin, service, owner, company, master.
  // Для ролей типа owner, company, master необходимо сделать проверку на доступность камеры этому пользователю
  rpc GetCameraCalendar(GetCameraCalendarRequest) returns (GetCameraCalendarResponse) {
    option (google.api.http) = {
      get: "/vc/api/v1/camera/{uid}/calendar"
    };
  }
  // Метод получения интервалов, когда доступны записи.
  // Метод доступен для: admin, service, owner, company, master.
  // Для ролей типа owner, company, master необходимо сделать проверку на доступность камеры этому пользователю
  rpc GetCameraIntervals(GetCameraIntervalsRequest) returns (GetCameraIntervalsResponse) {
    option (google.api.http) = {
      get: "/vc/api/v1/camera/{uid}/intervals"
    };
  }
}

// Связь камеры и квартиры
message CameraRoom {
  // Идентификатор камеры
  string camera_uid = 1 [(google.api.field_behavior) = REQUIRED];
  // ОРПОН дома
  int64 orpon = 2 [(google.api.field_behavior) = REQUIRED];
  // Номер квартиры.
  // # Диапазон: 1..4
  string room_number = 3 [(google.api.field_behavior) = REQUIRED];
}

// Фильтр связок камеры и квартиры.
// При передаче массива в параметр фильтра элементы массива работают в выборке через ИЛИ.
// При передаче нескольких разных параметров фильтра они работают в выборке через И
message CameraRoomFilter {
  // По Идентификаторам камер.
  // # Диапазон: 0..100
  repeated string camera_uids = 1;
  // По ОРПОНам.
  // # Диапазон: 0..100
  repeated int64 orpons = 2;
  // По квартирам.
  // # Диапазон: 0..100
  repeated string room_numbers = 3;
}

// Постраничный вывод
message CameraRoomPaging {
  // Справочник типов направлений сортировки.
  // # Тип: byte
  enum DirectionType {
    // Значение не указано
    DIRECTION_TYPE_UNKNOWN = 0;
    // От большего к меньшему
    DESC = 1;
    // От меньшего к большему
    ASC = 2;
  }
  // Справочник типов значений сортировки.
  // # Тип: byte
  enum OrderByType {
    // Значение не указано
    ORDER_BY_TYPE_UNKNOWN = 0;
    // По Идентификатору камеры
    CAMERA_UID = 1;
    // По ОРПОН и номеру квартиры
    ORPON_ROOM_NUMBER = 2;
  }
  // Тип значения сортировки.
  // Если значение не передано, то будет взято значение по умолчанию CAMERA_UID
  OrderByType order_by_type = 1;
  // Тип направления сортировки.
  // # По умолчанию: DESC
  DirectionType direction_type = 2;
  // Количество записей на страницу.
  // Если значение 0 (не передано), то будет взято значение по умолчанию.
  // # Диапазон: 0..100.
  // # По умолчанию: 20
  int32 limit = 3;
  // Сдвиг.
  // # Диапазон: 0..2147483647
  int32 offset = 4;
}

// Камера
message Camera {
  // Идентификатор камеры
  string id = 1 [(google.api.field_behavior) = OUTPUT_ONLY];
  // uid камеры
  string uid = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
  // Название камеры
  string name = 3 [(google.api.field_behavior) = OUTPUT_ONLY];
  // Признак: онлайн камера или нет
  bool is_online = 4 [(google.api.field_behavior) = OUTPUT_ONLY];
  // Признак: Есть ли у камеры активный пользователь
  bool is_active_user_camera = 5 [(google.api.field_behavior) = OUTPUT_ONLY];
  // Дата и время изменения статуса камеры
  google.protobuf.Timestamp status_changed_at = 6 [(google.api.field_behavior) = OUTPUT_ONLY];
  // MAC-адрес камеры
  string mac = 7;
  // IP камеры
  string ip = 8 [(google.api.field_behavior) = OUTPUT_ONLY];
  // Внешний IP камеры
  string remote_ip = 9 [(google.api.field_behavior) = OUTPUT_ONLY];
  // Дата начала действия текущего тарифа
  google.protobuf.Timestamp tariff_started_at = 10 [(google.api.field_behavior) = OUTPUT_ONLY];
  // Дата окончания действия текущего тарифа
  google.protobuf.Timestamp tariff_ended_at = 11 [(google.api.field_behavior) = OUTPUT_ONLY];
  // Наименование тарифа
  string tariff_title = 12 [(google.api.field_behavior) = OUTPUT_ONLY];
  // Справочник типов камер
  enum Type {
    // Значение не указано
    TYPE_UNKNOWN = 0;
    // Регистратор
    DVR = 1;
    // Система управления видео
    VMS = 2;
    // RTSP-камера
    ROSE = 3;
    // IP-камера
    VIOLET = 4;
  }
  // Тип камеры
  Type type = 13 [(google.api.field_behavior) = INPUT_ONLY];
  // Идентификатор категории.
  // Камера - 1, домофон - 2, скуд - 3, шлагбаум - 4
  int32 camera_category_id = 14 [(google.api.field_behavior) = INPUT_ONLY];
  // РТСП-ссылка
  string rtsp_url = 15 [(google.api.field_behavior) = INPUT_ONLY];
  // Серийный номер
  string serial_number = 16 [(google.api.field_behavior) = INPUT_ONLY];
  // Идентификатор компании
  int32 company_id = 17 [(google.api.field_behavior) = INPUT_ONLY];
  // Ошибки валидации
  message ValidationError {
    // Поле rtsp_url должно быть заполнено.
    // Только для камер с типом ROSE
    message RtspUrlRequired {}
    // Только одно поле обязательно к заполнению mac или serial_number.
    // Для камер с типом VIOLET и DVR
    message OneFieldMacOrSerialNumberRequired {}
    // Причина
    oneof reason {
      // Поле rtsp_url должно быть заполнено
      RtspUrlRequired rtsp_url_required = 1;
      // Только одно поле обязательно к заполнению mac или serial_number
      OneFieldMacOrSerialNumberRequired one_field_mac_or_serial_number_required = 2;
    }
  }
}

// Фильтр камер
message CameraFilter {
  // Признак активности камеры
  google.protobuf.BoolValue is_active = 1;
  // Признак активности канала
  google.protobuf.BoolValue is_channel_alive = 2;
  // Статус камеры
  google.protobuf.BoolValue is_online = 3;
  // Тип камеры
  Camera.Type camera_type = 4;
}

// Постраничный вывод
message CameraPaging {
  // Справочник типов направлений сортировки.
  // # Тип: byte
  enum DirectionType {
    // Значение не указано
    DIRECTION_TYPE_UNKNOWN = 0;
    // От большего к меньшему
    DESC = 1;
    // От меньшего к большему
    ASC = 2;
  }
  // Справочник типов значений сортировки.
  // # Тип: byte
  enum OrderByType {
    // Значение не указано
    ORDER_BY_TYPE_UNKNOWN = 0;
    // По идентификатору
    UID = 1;
  }
  // Тип значения сортировки.
  // Если значение не передано, то будет взято значение по умолчанию
  OrderByType order_by_type = 1;
  // Тип направления сортировки.
  // # По умолчанию: DESC
  DirectionType direction_type = 2;
  // Количество записей на страницу.
  // Если значение 0 (не передано), то будет взято значение по умолчанию.
  // # Диапазон: 0..100.
  // # По умолчанию: 20
  int32 limit = 3;
  // Сдвиг.
  // # Диапазон: 0..2147483647
  int32 offset = 4;
}
// Ограничение выборки камер
message CameraScope {
  // Внешний идентификатор компании
  int32 vc_company_id = 1;
}

// Запрос на получение списка камер
message GetCameraListRequest {
  // Ограничение выборки
  CameraScope scope = 1;
  // Фильтр
  CameraFilter filter = 2;
  // Вариант разбиения на страницы
  oneof pagination {
    // Постраничный вывод
    CameraPaging paging = 3;
  }
}

// Ответ на получение списка камер
message GetCameraListResponse {
  // Ошибка запроса
  message Error {
    // Причина ошибки
    oneof reason {
      // Ошибка валидации
      ValidationError validation = 1;
    }
  }
  // Список
  message Data {
    // Список Camera
    repeated Camera items = 1;
    // Всего количество
    int32 total = 2;
  }
  // Тип ответа
  oneof type {
    // Список
    Data data = 1;
    // Ошибка
    Error error = 2;
  }
}

// Запрос получения камеры
message GetCameraRequest {
  // Ограничение выборки
  CameraScope scope = 1 [(google.api.field_behavior) = REQUIRED];
  // uid камеры
  string uid = 2 [(google.api.field_behavior) = REQUIRED];
}

// Ответ на запрос получения камеры
message GetCameraResponse {
  // Ошибка запроса
  message Error {
    // Причина ошибки
    oneof reason {
      // Ошибка валидации
      ValidationError validation = 1;
    }
  }
  // Тип ответа
  oneof type {
    // Камера
    Camera data = 1;
    // Ошибка
    Error error = 2;
  }
}

// Запрос получения камеры
message GetCameraRtspUrlExternalIdRequest {
  // Идентификатор камеры в vcfront.
  // # Тип: Guid
  string external_id = 1 [(google.api.field_behavior) = REQUIRED];
}

// Ответ на запрос получения RTSP-ссылки по идентификатору камеры в vcfront
message GetCameraRtspUrlExternalIdResponse {
  // RTSP-ссылка
  message CameraRtspUrl {
    // RTSP-ссылка
    string rtsp_url = 1;
  }
  // Ошибка запроса получения списка камер
  message Error {
    // Причина ошибки
    oneof reason {
      // Ошибка валидации
      ValidationError validation = 1;
    }
  }
  // Тип результата
  oneof type {
    // RTSP-ссылка
    CameraRtspUrl data = 1;
    // Ошибка
    Error error = 2;
  }
}

// Запрос привязки камеры и квартиры
message PutCameraRoomAttachRequest {
  // Связь Camera и Room
  CameraRoom data = 1 [(google.api.field_behavior) = REQUIRED];
}

// Ответ привязки камеры и квартиры
message PutCameraRoomAttachResponse {
  // Ошибка запроса
  message Error {
    // Причина ошибки
    oneof reason {
      // Ошибка валидации
      ValidationError validation = 1;
    }
  }
  // Тип ответа
  oneof type {
    // Ошибка
    Error error = 1;
  }
}

// Запрос пакетной привязки камер и квартир
message PutCameraRoomAttachListRequest {
  // Массив связей Camera и Room
  repeated CameraRoom data = 1;
}

// Ответ на запрос пакетной привязки камер и квартир
message PutCameraRoomAttachListResponse {
  // Ошибка запроса
  message Error {
    // Причина ошибки
    oneof reason {
      // Ошибка валидации
      ValidationError validation = 1;
    }
  }
  // Тип ответа
  oneof type {
    // Ошибка
    Error error = 1;
  }
}

// Запрос отвязки камеры и квартиры
message PutCameraRoomDetachRequest {
  // Связь Camera и Room
  CameraRoom data = 1 [(google.api.field_behavior) = REQUIRED];
}

// Ответ отвязки камеры и квартиры
message PutCameraRoomDetachResponse {
  // Ошибка запроса
  message Error {
    // Причина ошибки
    oneof reason {
      // Ошибка валидации
      ValidationError validation = 1;
    }
  }
  // Тип ответа
  oneof type {
    // Ошибка
    Error error = 1;
  }
}

// Запрос пакетной отвязки камер и квартир
message PutCameraRoomDetachListRequest {
  // Массив связей Camera и Room
  repeated CameraRoom data = 1;
}

// Ответ на запрос пакетной отвязки камер и квартир
message PutCameraRoomDetachListResponse {
  // Ошибка запроса
  message Error {
    // Причина ошибки
    oneof reason {
      // Ошибка валидации
      ValidationError validation = 1;
    }
  }
  // Тип ответа
  oneof type {
    // Ошибка
    Error error = 1;
  }
}


// Запрос получения количества связей камеры и квартиры
message GetCameraRoomCountRequest {
  // Фильтр
  CameraRoomFilter filter = 1;
}

// Ответ получения количества связей камеры и квартиры
message GetCameraRoomCountResponse {
  // Ошибка запроса
  message Error {
    // Причина ошибки
    oneof reason {
      // Ошибка валидации
      ValidationError validation = 1;
    }
  }
  // Тип ответа
  oneof type {
    // Всего количество
    int32 data = 1;
    // Ошибка
    Error error = 2;
  }
}

// Запрос получения списка связей камеры и квартиры
message GetCameraRoomListRequest {
  // Фильтр
  CameraRoomFilter filter = 1;
  // Вариант разбиения на страницы
  oneof pagination {
    // Постраничный вывод
    CameraRoomPaging paging = 2;
  }
}

// Ответ получения списка связей камеры и квартиры
message GetCameraRoomListResponse {
  // Ошибка запроса
  message Error {
    // Причина ошибки
    oneof reason {
      // Ошибка валидации
      ValidationError validation = 1;
    }
  }
  // Тип ответа
  oneof type {
    // Связь камеры и квартиры
    CameraRoom data = 1;
    // Ошибка
    Error error = 2;
  }
}

// Запрос удаления камеры
message DeleteCameraRequest {
  // Идентификатор камеры в vcfront.
  // # Тип: Guid
  string uid = 1 [(google.api.field_behavior) = REQUIRED];
  // Флаг полного (безвозвратного) удаления камеры
  bool is_delete_permanently = 2;
}

// Ответ на запрос удаления камеры
message DeleteCameraResponse {
  // Ошибка запроса
  message Error {
    // Причина ошибки
    oneof reason {
      // Ошибка валидации
      ValidationError validation = 1;
    }
  }
  // Тип ответа
    oneof type {
      // Ошибка
      Error error = 1;
    }
}

// Запрос создания камеры
message PostCameraRequest {
  // Камера
  Camera data = 1 [(google.api.field_behavior) = REQUIRED];
}

// Ответ на запрос создания камеры
message PostCameraResponse {
  // Ошибка запроса
  message Error {
    // Ошибка в сервисе ВН
    message VcError {
      // Текст ошибки
      string text = 1;
    }
    // Причина ошибки
    oneof reason {
      // Ошибка валидации
      ValidationError validation = 1;
      // Ошибка валидации
      Camera.ValidationError camera_validation = 2;
      // Ошибка в сервисе ВН
      VcError vc = 3;
    }
  }
  // Тип ответа
  oneof type {
    // Ошибка
    Error error = 1;
  }
}

// Запрос получения дней, когда доступны записи
message GetCameraCalendarRequest {
  // Идентификатор камеры в vcfront.
  // # Тип: Guid
  string uid = 1 [(google.api.field_behavior) = REQUIRED];
  // Смещение от UTC в минутах
  google.protobuf.Int32Value offset = 2;
}

// Ответ на запрос получения дней, когда доступны записи
message GetCameraCalendarResponse {
  // Дни с записями
  message Caledar {
    // День с записью
    repeated string items = 1;
  }
  // Ошибка запроса
  message Error {
    // Ошибка в сервисе ВН
    message VcError {
      // Текст ошибки
      string text = 1;
    }
    // Причина ошибки
    oneof reason {
      // Ошибка валидации
      ValidationError validation = 1;
      // Ошибка в сервисе ВН
      VcError vc = 2;
    }
  }
  // Тип ответа
  oneof type {
    // Дни с записями
    Caledar data = 1;
    // Ошибка
    Error error = 2;
  }
}

// Запрос получения интервалов, когда доступны записи
message GetCameraIntervalsRequest {
  // Идентификатор камеры в vcfront.
  // # Тип: Guid
  string uid = 1 [(google.api.field_behavior) = REQUIRED];
  // Смещение от UTC в минутах
  google.protobuf.Int32Value offset = 2;
}

// Ответ на запрос получения интервалов, когда доступны записи
message GetCameraIntervalsResponse {
  // Интервалы
  message Interval {
    // Интервал
    message Item {
      // Значение интервала с.
      // # Тип: DateTime
      google.protobuf.Timestamp since_at = 1;
      // Значение интервала до.
      // # Тип: DateTime
      google.protobuf.Timestamp till_at = 2;
    }
    // Список интервалов
    repeated Item items = 1;
  }
  // Ошибка запроса
  message Error {
    // Ошибка в сервисе ВН
    message VcError {
      // Текст ошибки
      string text = 1;
    }
    // Причина ошибки
    oneof reason {
      // Ошибка валидации
      ValidationError validation = 1;
      // Ошибка в сервисе ВН
      VcError vc = 2;
    }
  }
  // Тип ответа
  oneof type {
    // Интервалы
    Interval data = 1;
    // Ошибка
    Error error = 2;
  }
}

// Ошибки валидации.
// Эти проверки выполняются до обращения в базу данных
message ValidationError {
  // Путь к полю в формате наименования прото
  string path = 1 [(google.api.field_behavior) = REQUIRED];
  // Валидационное сообщение
  string message = 2 [(google.api.field_behavior) = REQUIRED];
}
