// Copyright © 2019 The Things Network Foundation, The Things Industries B.V.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";

import "github.com/envoyproxy/protoc-gen-validate/validate/validate.proto";
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
import "google/api/annotations.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/field_mask.proto";
import "lorawan-stack/api/end_device.proto";
import "lorawan-stack/api/picture.proto";

package ttn.lorawan.v3;

option go_package = "go.thethings.network/lorawan-stack/v3/pkg/ttnpb";

// TODO: Migrate away from GoGo Protobuf (https://github.com/TheThingsNetwork/lorawan-stack/issues/2798).
option (gogoproto.goproto_registration) = true;

message QRCodeFormat {
  string name = 1 [(validate.rules).string.max_len = 100];
  string description = 2 [(validate.rules).string.max_len = 200];
  // The entity fields required to generate the QR code.
  google.protobuf.FieldMask field_mask = 3;
}

message QRCodeFormats {
  // Available formats. The map key is the format identifier.
  map<string, QRCodeFormat> formats = 1 [(validate.rules).map.keys.string = {pattern: "^[a-z0-9](?:[-]?[a-z0-9]){2,}$", max_len: 36}];
}

message GetQRCodeFormatRequest {
  // QR code format identifier. Enumerate available formats with rpc ListFormats in the EndDeviceQRCodeGenerator service.
  string format_id = 1 [(validate.rules).string = {pattern: "^[a-z0-9](?:[-]?[a-z0-9]){2,}$", max_len: 36}];
}

message GenerateEndDeviceQRCodeRequest {
  // QR code format identifier. Enumerate available formats with rpc ListFormats in the EndDeviceQRCodeGenerator service.
  string format_id = 1 [(validate.rules).string = {pattern: "^[a-z0-9](?:[-]?[a-z0-9]){2,}$", max_len: 36}];
  // End device to use as input to generate the QR code.
  EndDevice end_device = 2 [(validate.rules).message.required = true];

  message Image {
    // Requested QR code image dimension in pixels.
    uint32 image_size = 1 [(validate.rules).uint32 = {gte: 10, lte: 1000}];
  }
  // If set, the server will render the QR code image according to these settings.
  Image image = 3;
}

message GenerateQRCodeResponse {
  // Text representation of the QR code contents.
  string text = 1;
  // QR code in PNG format, if requested.
  Picture image = 2;
}

message ParseEndDeviceQRCodeRequest {
  // QR code format identifier.
  // Enumerate available formats with the rpc `ListFormats`.
  // If this field is not specified, the server will attempt to parse the data with each known format.
  string format_id = 1 [(validate.rules).string = {pattern: "^[a-z0-9](?:[-]?[a-z0-9]){2,}$|^$", max_len: 36}];
  // Raw QR code contents.
  bytes qr_code = 2 [(validate.rules).bytes = {min_len: 10, max_len: 1024}];
}

message ParseEndDeviceQRCodeResponse {
  // Identifier of the format used to successfully parse the QR code data.
  string format_id = 1;
  EndDeviceTemplate end_device_template = 2;
}

service EndDeviceQRCodeGenerator {
  // Return the QR code format.
  rpc GetFormat(GetQRCodeFormatRequest) returns (QRCodeFormat) {
    option (google.api.http) = {
      get: "/qr-codes/end-devices/formats/{format_id}"
    };
  };

  // Returns the supported formats.
  rpc ListFormats(google.protobuf.Empty) returns (QRCodeFormats) {
    option (google.api.http) = {
      get: "/qr-codes/end-devices/formats"
    };
  };

  // Generates a QR code.
  rpc Generate(GenerateEndDeviceQRCodeRequest) returns (GenerateQRCodeResponse) {
    option (google.api.http) = {
      post: "/qr-codes/end-devices",
      body: "*"
    };
  };

  // Parse QR Codes of known formats and return the information contained within.
  rpc Parse(ParseEndDeviceQRCodeRequest) returns (ParseEndDeviceQRCodeResponse){
    option (google.api.http) = {
      post: "/qr-code/end-devices/parse",
      body: "*"
      additional_bindings {
        post: "/qr-code/end-devices/{format_id}/parse"
        body: "*"
      }
    };
  }
}
