syntax = "proto3";

option java_package = "com.soulfiremc.grpc.generated";
option java_multiple_files = true;

package soulfire.v1;

import "soulfire/api_docs.proto";
import "google/api/annotations.proto";
import "google/api/field_behavior.proto";

// Represents an unrestricted global command scope.
// Commands executed in this scope have access to all instances and bots.
// Requires the GLOBAL_COMMAND_EXECUTION permission.
message GlobalCommandScope {
}

// Represents a command scope restricted to a specific instance.
// Commands executed in this scope can only affect the specified instance and its bots.
// Requires the INSTANCE_COMMAND_EXECUTION permission for the specified instance.
message InstanceCommandScope {
  // The unique identifier (UUID) of the instance to scope commands to.
  // Must be a valid UUID string.
  string instance_id = 1 [(google.api.field_behavior) = REQUIRED, (soulfire.v1.api_field).format = "uuid"];
}

// Represents a command scope restricted to a specific bot within an instance.
// Commands executed in this scope can only affect the specified bot.
// Requires the INSTANCE_COMMAND_EXECUTION permission for the parent instance.
message BotCommandScope {
  // The unique identifier (UUID) of the instance containing the bot.
  // Must be a valid UUID string.
  string instance_id = 1 [(google.api.field_behavior) = REQUIRED, (soulfire.v1.api_field).format = "uuid"];
  // The unique identifier (UUID) of the bot (profile ID) to scope commands to.
  // Must be a valid UUID string matching the bot's account profile ID.
  string bot_id = 2 [(google.api.field_behavior) = REQUIRED, (soulfire.v1.api_field).format = "uuid"];
}

// Defines the execution context for a command, determining which instances
// and bots the command can affect. The scope also determines required permissions.
message CommandScope {
  oneof scope {
    // Execute command with global (unrestricted) access to all instances and bots.
    GlobalCommandScope global = 1;
    // Execute command restricted to a specific instance and its bots.
    InstanceCommandScope instance = 2;
    // Execute command restricted to a specific bot within an instance.
    BotCommandScope bot = 3;
  }
}

// Request message for executing a server command.
message CommandRequest {
  // The execution scope that determines which instances/bots the command can affect
  // and what permissions are required. Must be set to one of the scope options.
  CommandScope scope = 4 [(google.api.field_behavior) = REQUIRED];
  // The command string to execute. This follows the Brigadier command format,
  // e.g., "help", "move 100 64 200", "say Hello world".
  // Leading/trailing whitespace will be stripped before execution.
  string command = 3 [(google.api.field_behavior) = REQUIRED];
}

// Response message containing the result of command execution.
message CommandResponse {
  // The exit code returned by the command.
  // - 0: Command failed or had no effect (e.g., syntax error, no targets found)
  // - 1 (Command.SINGLE_SUCCESS): Command executed successfully
  // - >1: Command succeeded and affected multiple targets (count of affected items)
  // Note: Syntax errors return 0 and error details are sent via the logging system.
  int32 code = 1 [(google.api.field_behavior) = REQUIRED];
}

// Request message for getting tab-completion suggestions for a partial command.
message CommandCompletionRequest {
  // The execution scope that determines which instances/bots are visible
  // for completion suggestions. Must be set to one of the scope options.
  CommandScope scope = 5 [(google.api.field_behavior) = REQUIRED];
  // The partial command string to complete. May be an incomplete command
  // that the user is typing, e.g., "mov" or "move 100 ".
  string command = 3 [(google.api.field_behavior) = REQUIRED];
  // The cursor position within the command string (0-indexed).
  // Completions will be generated for the token at this position.
  // Typically this is the length of the command string for end-of-line completion.
  int32 cursor = 4 [(google.api.field_behavior) = REQUIRED];
}

// A single tab-completion suggestion.
message CommandCompletion {
  // The suggested text to insert at the cursor position.
  // This is the actual completion value, not the full command.
  string suggestion = 1 [(google.api.field_behavior) = REQUIRED];
  // Optional tooltip providing additional context about this suggestion.
  // May contain formatted text explaining what the suggestion does.
  // If not present, no tooltip should be displayed.
  optional string tooltip = 2;
}

// Response message containing tab-completion suggestions.
message CommandCompletionResponse {
  // List of completion suggestions for the partial command.
  // May be empty if no completions are available.
  // Suggestions are generated based on the command's Brigadier definition
  // and the current execution scope's visibility.
  repeated CommandCompletion suggestions = 1 [(google.api.field_behavior) = REQUIRED];
}

// Service for executing server commands and retrieving tab-completion suggestions.
// Commands are executed using the Brigadier command framework and support various
// operations including bot control, pathfinding, inventory management, and administration.
// All operations require appropriate permissions based on the specified command scope.
service CommandService {
  // Executes a command string within the specified scope.
  // The command is parsed and executed using the Brigadier command dispatcher.
  //
  // Permission requirements depend on the scope:
  // - Global scope: Requires GLOBAL_COMMAND_EXECUTION permission
  // - Instance scope: Requires INSTANCE_COMMAND_EXECUTION for the instance
  // - Bot scope: Requires INSTANCE_COMMAND_EXECUTION for the parent instance
  //
  // Returns:
  // - CommandResponse with the command's exit code
  //
  // Errors:
  // - INVALID_ARGUMENT: If the scope is not set
  // - PERMISSION_DENIED: If the user lacks required permissions
  // - INTERNAL: If an unexpected error occurs during execution
  rpc ExecuteCommand (CommandRequest) returns (CommandResponse) {
    option (google.api.http) = {
      post: "/v1/commands:execute"
      body: "*"
    };
    option (soulfire.v1.api_method) = {
      display_name: "Execute command"
      scope: "command.scope"
      side_effects: "Executes a Brigadier command in the requested scope."
    };
  }

  // Retrieves tab-completion suggestions for a partial command.
  // Uses Brigadier's completion system to generate context-aware suggestions
  // based on the command structure and current cursor position.
  //
  // Permission requirements depend on the scope (same as ExecuteCommand).
  //
  // Returns:
  // - CommandCompletionResponse with a list of possible completions
  //
  // Errors:
  // - INVALID_ARGUMENT: If the scope is not set
  // - PERMISSION_DENIED: If the user lacks required permissions
  // - INTERNAL: If an unexpected error occurs during completion
  rpc TabCompleteCommand (CommandCompletionRequest) returns (CommandCompletionResponse) {
    option (google.api.http) = {
      post: "/v1/commands:complete"
      body: "*"
    };
    option (soulfire.v1.api_method) = {
      display_name: "Complete command"
      scope: "command.scope"
    };
  }
}
