/*
Proto contract of Printer Controller API
This is a collection that allows for:
- Managing starting and stopping of the Printer
- Sending jobs (Controller mode)
- Receiving jobs (Worker mode)
- Getting notifications from the printer
- Getting the state of the printer

Version     Date            Author      Comment
V1.0.0      10-04-2024      MiAl        Initial versioning
V1.1.0      07-01-2024      KdJ         First version of the actual proto contract
V1.0.1      14-01-2025      KdJ         Updated proto references
V1.1.0      15-02-2025      MiAl        Cleaned up comments, added server stream endpoints and corrected messages
v1.2.0      12-03-2025      MiAl        Adjusted server stream for job request
v1.3.0      24-03-2025      MiAl        Renamed endpoints and REST paths
v1.4.0      17-04-2026      SGi         Add endpoints for Recipe and Variable
*/

syntax = "proto3";

import "Interfaces/google/api/annotations.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/timestamp.proto";
import "Interfaces/PrintManager/Protos/V1/bergstein.digi.printmanager.paging.proto";

package printer;

option csharp_namespace = "Bergstein.Digi.Shared.Interfaces.Printer.Protos.V1";

/*
Service for interacting with the printer controller.
Contract serves as a basic implementation of a DIGI printer.
*/
service PrinterControllerService {
  /*
  Endpoint for starting the printer.

  Returns on a success:
  - OK (0)

  Returns on a failure:
  - CANCELLED (1) status when you abort the call
  - PERMISSION_DENIED (7) status when you do not have the right role
  - INTERNAL (13) status when something went wrong on the server (please contact your administrator in this case)
  - UNAUTHENTICATED (16) status when you do not provide the required access token
  */
  rpc Start (google.protobuf.Empty) returns (google.protobuf.Empty) {
    option (google.api.http) = {
      put: "/printer_controller/v1/printer_controller/start"
    };
  }

  /*
  Endpoint for stopping the printer.

  Returns on a success:
  - OK (0)

  Returns on a failure:
  - CANCELLED (1) status when you abort the call
  - PERMISSION_DENIED (7) status when you do not have the right role
  - INTERNAL (13) status when something went wrong on the server (please contact your administrator in this case)
  - UNAUTHENTICATED (16) status when you do not provide the required access token
  */
  rpc Stop (google.protobuf.Empty) returns (google.protobuf.Empty) {
    option (google.api.http) = {
      put: "/printer_controller/v1/printer_controller/stop"
    };
  }

  /*
  Endpoint for sending a job to the printer (Controller- & Worker-mode).

  Returns on a success:
  - OK (0) response message

  Returns on a failure:
  - CANCELLED (1) status when you abort the call
  - INVALID_ARGUMENT status when the one or more fields no not fall within the set format/limits.
  - PERMISSION_DENIED (7) status when you do not have the right role
  - INTERNAL (13) status when something went wrong on the server (please contact your administrator in this case)
  - UNAUTHENTICATED (16) status when you do not provide the required access token
  */
  rpc SendPrintJob (PrintJobRequest) returns (PrintJobResponse) {
    option (google.api.http) = {
      post: "/printer_controller/v1/printer_controller/print_job"
      body: "*"
    };
  }

  /*
  Endpoint for getting the currently active job state.

  Returns on a success:
  - OK (0) response message

  Returns on a failure:
  - CANCELLED (1) status when you abort the call
  - INVALID_ARGUMENT status when the one or more fields no not fall within the set format/limits
  - PERMISSION_DENIED (7) status when you do not have the right role
  - INTERNAL (13) status when something went wrong on the server (please contact your administrator in this case)
  - UNAUTHENTICATED (16) status when you do not provide the required access token
  */
  rpc GetPrintJobStatus (google.protobuf.Empty) returns (JobStatusResponse) {
    option (google.api.http) = {
      get: "/printer_controller/v1/printer_controller/job_state"
    };
  }

  /*
  Endpoint for getting the printer state.

  Returns on a success:
  - OK (0) response message

  Returns on a failure:
  - CANCELLED (1) status when you abort the call
  - PERMISSION_DENIED (7) status when you do not have the right role
  - INTERNAL (13) status when something went wrong on the server (please contact your administrator in this case)
  - UNAUTHENTICATED (16) status when you do not provide the required access token
  */
  rpc GetPrinterState (google.protobuf.Empty) returns (PrinterStatusResponse) {
    option (google.api.http) = {
      get: "/printer_controller/v1/printer_controller/printer_state"
    };
  }

  /*
  Endpoint for getting all the notifications.

  Returns on a success:
  - OK (0) response message

  Returns on a failure:
  - CANCELLED (1) status when you abort the call
  - INVALID_ARGUMENT status when the one or more fields no not fall within the set format/limits
  - PERMISSION_DENIED (7) status when you do not have the right role
  - INTERNAL (13) status when something went wrong on the server (please contact your administrator in this case)
  - UNAUTHENTICATED (16) status when you do not provide the required access token
  */
  rpc GetNotifications (GetNotificationRequest) returns (NotificationsResponse) {
    option (google.api.http) = {
      get: "/printer_controller/v1/printer_controller/notifications"
    };
  }

  /*
  Endpoint for subscribing when an print job status has updated.

  Returns on a success:
  - OK (0) response message

  Returns on a failure:
  - CANCELLED (1) status when you abort the call
  - INVALID_ARGUMENT status when the one or more fields no not fall within the set format/limits
  - PERMISSION_DENIED (7) status when you do not have the right role
  - INTERNAL (13) status when something went wrong on the server (please contact your administrator in this case)
  - UNAUTHENTICATED (16) status when you do not provide the required access token
  */
  rpc OnJobStatusUpdated (google.protobuf.Empty) returns (stream JobStatusResponse) {
  }

  /*
  Endpoint for the notification system

  Returns on a success:
  - OK (0) response message stream

  Returns on a failure:
  - CANCELLED (1) status when you abort the call
  - INVALID_ARGUMENT status when the one or more Printer Connection fields no not fall within the set format/limits
  - PERMISSION_DENIED (7) status when you do not have the right role
  - INTERNAL (13) status when something went wrong on the server (please contact your administrator in this case)
  - UNAUTHENTICATED (16) status when you do not provide the required access token
  */
  rpc OnNotification (google.protobuf.Empty) returns (stream NotificationResponse) {
  }

  
  /*
  Endpoint for subscribing when an print job status has updated.

  Returns on a success:
  - OK (0) response message stream

  Returns on a failure:
  - CANCELLED (1) status when you abort the call
  - PERMISSION_DENIED (7) status when you do not have the right role
  - INTERNAL (13) status when something went wrong on the server (please contact your administrator in this case)
  - UNAUTHENTICATED (16) status when you do not provide the required access token
  */
  rpc OnPrinterStatusUpdated (google.protobuf.Empty) returns (stream PrinterStatusResponse) {
  }

  /*
  Endpoint for the printer to request a job (Worker mode).
  Its expected that the client will take this request, process it, and sends the resulting job.

  Returns on a success:
  - OK (0) response message stream

  Returns on a failure:
  - CANCELLED (1) status when you abort the call
  - PERMISSION_DENIED (7) status when you do not have the right role
  - INTERNAL (13) status when something went wrong on the server (please contact your administrator in this case)
  - UNAUTHENTICATED (16) status when you do not provide the required access token
  */
  rpc OnRequestJob (PrintJobServerSubscription) returns (stream PrintJobRequestParameters) {
  }
}

// Message holding the information of a job to send to a printer.
message PrintJobRequest {
  // The actual job data.
  PrintFile job = 1;
  // The original print job request parameters.
  PrintJobRequestParameters parameters = 2;
}

// The response when sending a print job.
message PrintJobResponse {
  // The printer internal job id number.
  string job_id = 1;
  // The name of the job. The maximum length is 50 characters.
  string job_name = 2;
}

// The printer job server subscription for listening on worker mode requests.
message PrintJobServerSubscription {
  // For now we provide nothing in the request.
}

message PrintJobRequestParameters {
  /*
  The request job template id.
  Either this field is set to a value greater than 0 to indicate a fetch by ID (this is default)
  or the job template customer reference field.
  */
  string job_template_id = 1;
  /*
  The request job template customer reference.
  Either this field is set to a value greater than 0 to indicate a fetch by ID (this is default)
  or the job template id field.
  */
  string job_template_customer_reference = 2;
  /*
  The binary (little-endian) sides number this image should be printed on to a maximum of 32 layers. 
  For example: when its needed to print this image on the first and second layer, you activate those entries bitwise (little endian):
  With a binary notation this means: 0000 0000 0000 0011 => decimal 3. So we store the number 3 here.
  */
  uint32 enabled_layers = 3;
  /*
  The binary (little-endian) sides number this image should be printed on to a maximum of 64. 
  For example: when its needed to print this image with the first and third product, you activate those entries bitwise (little-endian):
  With a binary notation this means: 0000 0000 0000 0101 => decimal 5. So we store the decimal number 5.
  */
  uint64 enabled_products = 4;
  /*
  The binary (little-endian) sides number of this image that shall be shown, to a maximum of 64 sides. 
  For example: when its needed to show this image with the first and third product, you activate those entries bitwise (little-endian):
  With a binary notation this means: 0000 0000 0000 0101 => decimal 5. So we store the decimal number 5.
  */
  uint32 enabled_sides = 5;
  /*
  The PrintJobMode for this job.
  */
  PrintJobMode print_job_mode = 6;
}

// The job printing modus.
message PrintJobMode {
  // The print mode for this specific job.
  PrintMode print_mode = 1;
  // When set to batch, we need an amount of prints, called the print count.
  uint32 count = 2;
}

// The enum options of the type of print mode for the printer.
enum PrintMode {
  // The print mode is unknown.
  PrintMode_Unknown = 0;
  // Single print mode.
  PrintMode_Single = 1;
  // Batch print mode.
  PrintMode_Batch = 2;
  // Continuous print mode.
  PrintMode_Continuous = 3;
}

// The job status response that holds the last state of a given printer job.
message JobStatusResponse {
  // The printer internal job id number.
  string job_id = 1;
  // The name of the job. The maximum length is 50 characters.
  string job_name = 2;
  // The status of the job.
  JobStatus status = 3;
}

// The status of the job.
enum JobStatus {
  // The printer status is unknown. This is an invalid value.
  JobStatus_Unknown = 0;
  // The job is waiting to be printed.
  JobStatus_Idle = 1;
  // The job is queued.
  JobStatus_Queued = 2;
  // The job is active and awaiting start, loading and/or unloading. 
  JobStatus_Active = 3;
  // The job is printing.
  JobStatus_Printing = 4;
  // The job is finished.
  JobStatus_Finished = 5;
  // The job is canceled by the user.
  JobStatus_Canceled = 6;
  // The job is stopped due to an error.
  JobStatus_Error = 7;
}

// The printer status response signaling the current printer state.
message PrinterStatusResponse {
  // The current status of the printer.
  PrinterStatus status = 1;
}

// The get notification request.
message GetNotificationRequest {
  // TODO: Expose filter field for notifications.
}

// The notification response, holding a collection of notifications.
message NotificationsResponse {
  // The notification collection.
  repeated Notification notifications = 1;
}

// The notification response, holding a single notification.
message NotificationResponse {
  // The notification.
  Notification notification = 1;
}

// The notification message. This is an message like a log, but for specific HMI/operator use.
message Notification {
  // The identification of the notification.
  string id = 1;
  // The notification type, that signals what urgency level is signaled.
  NotificationType type = 2;
  // The start time of this message.
  google.protobuf.Timestamp start_time = 3;
  // The end time of this message. When null/default this means the message is still active.
  google.protobuf.Timestamp end_time = 4;
  // The component name to which this notification is associated with. The maximum length is 50 characters.
  string component_name = 5;
  // The message content. The maximum length is 250 characters.
  string content = 6;

}

// The notification type, that signals what urgency level is signaled.
enum NotificationType {
  // The notification type is unknown. This type is invalid.
  NotificationType_Unknown = 0;
  // The notification message is informational. No action is required by an operator.
  NotificationType_Info = 1;
  // The notification message signs a warning. An imminent error could occur in the near future if left unhandled by an operator.
  NotificationType_Warning = 2;
  // The notification message signs an error. An error has occurred and the machine has stopped, an operator must resolve this to continue.
  NotificationType_Error = 3;
}

// The enum options of the status of the printer
enum PrinterStatus {
  // The printer status type is unknown. This status is invalid.
  PrinterStatus_Unknown = 0;
  // The printer is in idle. Awaiting an command to print.
  PrinterStatus_Idle = 1;
  // The printer is starting. Transitioning from Idle to Started.
  PrinterStatus_Starting = 2;
  // The printer has started. Currently printing, loading and/or unloading.
  PrinterStatus_Started = 3;
  // The printer is stopping. Transitioning to Stopped.
  PrinterStatus_Stopping = 4;
  // The printer has stopped. Waiting start signal.
  PrinterStatus_Stopped = 5;
  // The printer is in error. Awaiting operator action. Review the active Notification(s) to resolve the error.
  PrinterStatus_Error = 6;
}

// The request for a PrintFile.
message PrintFile {
  // The name of the file.
  string name = 1;
  // The type of the file (extension).
  FileType type = 2;
  // file data as a base64 string.
  string file_data = 3;
}

// The enum options of the type of storage for the associated File.
// In the future this will be imported from the FileApi.
enum FileType {
  // The file type is unknown and therefore invalid. This can only arise when the file type could not be recognized by the system.
  FileType_Unknown = 0;
  // Print document format (send file type).
  FileType_PDF = 1;
  // ISI format (RIP result type).
  FileType_ISI = 2;
  // DIGI Print format.
  FileType_TIFF = 3;
  // Collected DIGI print format.
  FileType_DJOB = 4;
  // Bitmap format (for generating preview).
  FileType_BMP = 5;
  // Portable Network Graphics (PNG).
  FileType_PNG = 6;
  // Archive format.
  FileType_ZIP = 7;
}

// Service for creating, reading, updating, deleting recipes.
service RecipeService {
    
  /*
  Endpoint for creating recipe in the system.

  This is only accessible for Administrator accounts.

  Returns on a success:
  - the created recipe

  Returns on a failure:
  - CANCELLED (1) status when you abort the call
  - INVALID_ARGUMENT status when the one or more recipe fields no not fall within the set format/limits.
  - PERMISSION_DENIED (7) status when you do not have the right role
  - INTERNAL (13) status when something went wrong on the server (please contact your administrator in this case)
  - UNAUTHENTICATED (16) status when you do not provide the required access token
  */
  rpc CreateRecipe (CreateRecipeRequest) returns (CreateRecipeReply) {
    option (google.api.http) = {
      post: "/recipe_module/v1/recipe"
      body: "*"
    };
  }

  /*
  Endpoint for a getting a single recipe in the system.

  This is only accessible for Administrator accounts or the requesting user.

  Returns on a success:
  - the requested recipe

  Returns on a failure:
  - CANCELLED (1) status when you abort the call
  - NOT_FOUND (5) status when the requested recipe (ID), to fetch, was not found
  - PERMISSION_DENIED (7) status when you do not have the right role
  - INTERNAL (13) status when something went wrong on the server (please contact your administrator in this case)
  - UNAUTHENTICATED (16) status when you do not provide the required access token
  */
  rpc GetRecipe (GetRecipeRequest) returns (GetRecipeReply) {
    option (google.api.http) = {
      get: "/recipe_module/v1/recipe/{name}"
    };
  }

  /*
  Endpoint for getting all the recipes in the system.

  This is only accessible for Administrator accounts.

  Returns on a success:
  - list of registered recipes

  Returns on a failure:
  - CANCELLED (1) status when you abort the call
  - PERMISSION_DENIED (7) status when you do not have the right role
  - INTERNAL (13) status when something went wrong on the server (please contact your administrator in this case)
  - UNAUTHENTICATED (16) status when you do not provide the required access token
  */
  rpc ListRecipe (ListRecipeRequest) returns (ListRecipeReply) {
    option (google.api.http) = {
      get: "/recipe_module/v1/recipe"
    };
  }

  /*
  Endpoint for updating a registered recipe in the system.

  This is only accessible for Administrator accounts or the requesting user.

  Returns on a success:
  - the updated recipe

  Returns on a failure:
  - CANCELLED (1) status when you abort the call
  - INVALID_ARGUMENT status when the one or more recipe fields no not fall within the set format/limits.
  - NOT_FOUND (5) status when the requested recipe (ID), to update, was not found
  - PERMISSION_DENIED (7) status when you do not have the right role
  - INTERNAL (13) status when something went wrong on the server (please contact your administrator in this case)
  - UNAUTHENTICATED (16) status when you do not provide the required access token
  */
  rpc UpdateRecipe (UpdateRecipeRequest) returns (UpdateRecipeReply) {
    option (google.api.http) = {
      patch: "/recipe_module/v1/recipe"
      body: "*"
    };
  }

  /*
  Endpoint for deleting a registered recipe in the system.

  This is only accessible for Administrator accounts.

  Returns on a success:
  - nothing; OK status (0)

  Returns on a failure:
  - CANCELLED (1) status when you abort the call
  - NOT_FOUND (5) when the requested recipe (ID), to remove, was not found
  - PERMISSION_DENIED (7) status when you do not have the right role
  - INTERNAL (13) status when something went wrong on the server (please contact your administrator in this case)
  - UNAUTHENTICATED (16) status when you do not provide the required access token
  */
  rpc DeleteRecipe (DeleteRecipeRequest) returns (google.protobuf.Empty) {
    option (google.api.http) = {
      delete: "/recipe_module/v1/recipe/{name}"
    };
  }
}

// The create recipe request. The Id field should be left at 0, since this is created by the database.
message CreateRecipeRequest {
  // The new recipe
  Recipe recipe = 1;
}

// The get recipe request.
message GetRecipeRequest {
  // The matching Id of the recipe to get.
  string name = 1;
}

// A request for listing all recipes.
message ListRecipeRequest {
  shared.PagingRequest paging = 1;
  bool descending = 2;
  Recipe order = 3;
  Recipe filter = 4;
}

// The update recipe request.
message UpdateRecipeRequest {
  // The recipe entity to update. 
  Recipe recipe = 1;
}

// The delete recipe request
message DeleteRecipeRequest {
  string name = 1;
}

// The recipe Reply.
message GetRecipeReply {
  // The recipe entity.
  Recipe recipe = 1;
}

// The recipe Reply.
message CreateRecipeReply {
  // The recipe entity.
  Recipe recipe = 1;
}

// The recipe Reply.
message UpdateRecipeReply {
  // The recipe entity.
  Recipe recipe = 1;
}

// The recipes Reply.
message ListRecipeReply {
  // The collection of recipes.
  repeated Recipe recipes = 1;
  shared.PagingReply paging = 2;
}

// A recipe entity.
message Recipe {
  // The id of the recipe. This is generated by the database.
  int64 id = 1;
  // The datetime when this recipe was created.
  google.protobuf.Timestamp created_date_time = 2;
  // The recipe name
  string name = 3;
  // The data of this recipe
  repeated Variable variables = 4;
}

// Service for reading variables.
service VariableService {
  /*
  Endpoint for a getting a single variable in the system.

  This is only accessible for Administrator accounts or the requesting user.

  Returns on a success:
  - the requested variable

  Returns on a failure:
  - CANCELLED (1) status when you abort the call
  - NOT_FOUND (5) status when the requested variable (ID), to fetch, was not found
  - PERMISSION_DENIED (7) status when you do not have the right role
  - INTERNAL (13) status when something went wrong on the server (please contact your administrator in this case)
  - UNAUTHENTICATED (16) status when you do not provide the required access token
  */
  rpc GetVariable (GetVariableRequest) returns (GetVariableReply) {
    option (google.api.http) = {
      get: "/variable_module/v1/variable/{id}"
    };
  }

  /*
  Endpoint for getting all the variables in the system.

  This is only accessible for Administrator accounts.

  Returns on a success:
  - list of registered variables

  Returns on a failure:
  - CANCELLED (1) status when you abort the call
  - PERMISSION_DENIED (7) status when you do not have the right role
  - INTERNAL (13) status when something went wrong on the server (please contact your administrator in this case)
  - UNAUTHENTICATED (16) status when you do not provide the required access token
  */
  rpc ListVariable (ListVariableRequest) returns (ListVariableReply) {
    option (google.api.http) = {
      get: "/variable_module/v1/variable"
    };
  }
}

// The get variable request.
message GetVariableRequest {
  // The matching Id of the variable to get.
  string id = 1;
}

// A request for listing all variables.
message ListVariableRequest {
  shared.PagingRequest paging = 1;
  bool descending = 2;
  Variable order = 3;
  Variable filter = 4;
}

// The variable Reply.
message GetVariableReply {
  // The variable entity.
  Variable variable = 1;
}

// The variables Reply.
message ListVariableReply {
  // The collection of variables.
  repeated Variable variables = 1;
  shared.PagingReply paging = 2;
}

// A variable entity.
message Variable {
  // The id of the variable.
  string id = 1;
  // The name of the variable. 
  string name = 2;
  // The data type of this variable. 
  DataType data_type = 3;
  // The category of the variable.
  string category = 4;
  // The component of the variable
  string component = 5;
  // flag whether eventlog is enabled
  bool eventlog = 6;
  // flag whether datalog is enabled
  bool datalog = 7;
  // flag whether recipe is enabled
  bool recipe = 8;
  // flag whether configuration is enabled
  bool configuration = 9;
  // the value of the variable (as string)
  string value = 10;
}

// The enum options of the Variable types.
enum DataType {
    // Unknown data type
    DATA_TYPE_UNKNOWN = 0;
    // boolean type
    DATA_TYPE_BOOLEAN = 1;
    // nulleable boolean type
    DATA_TYPE_NULLABLE_BOOLEAN = 2;
    // int type
    DATA_TYPE_INTEGER = 3;
    // float type
    DATA_TYPE_FLOAT = 4;
    // string type
    DATA_TYPE_STRING = 5;
    // date type
    DATA_TYPE_DATE = 6;
    // datetime type
    DATA_TYPE_DATE_TIME = 7;
    // time type
    DATA_TYPE_TIME = 8;
    // uint type
    DATA_TYPE_UNSIGNED_INTEGER = 9;
    // short type
    DATA_TYPE_SHORT = 10;
    // object type
    DATA_TYPE_OBJECT = 11;
}
