syntax = "proto3";

package tree;

import "pkg/services/tree/types.proto";

option go_package = "github.com/nspcc-dev/neofs-node/pkg/services/tree";

// `TreeService` provides an interface for working with distributed tree.
service TreeService {
  /* Client API */

  // Add adds new node to the tree. Invoked by a client.
  rpc Add (AddRequest) returns (AddResponse);
  // AddByPath adds new node to the tree by path. Invoked by a client.
  rpc AddByPath (AddByPathRequest) returns (AddByPathResponse);
  // Remove removes node from the tree. Invoked by a client.
  rpc Remove (RemoveRequest) returns (RemoveResponse);
  // Move moves node from one parent to another. Invoked by a client.
  rpc Move (MoveRequest) returns (MoveResponse);
  // GetNodeByPath returns list of IDs corresponding to a specific filepath.
  rpc GetNodeByPath (GetNodeByPathRequest) returns (GetNodeByPathResponse);
  // GetSubTree returns tree corresponding to a specific node.
  rpc GetSubTree (GetSubTreeRequest) returns (stream GetSubTreeResponse);

  /* Synchronization API */

  // Apply pushes log operation from another node to the current.
  // The request must be signed by a container node.
  rpc Apply (ApplyRequest) returns (ApplyResponse);
}

message AddRequest {
  message Body {
    bytes container_id = 1;
    string tree_id = 2;
    uint64 parent_id = 3;
    repeated KeyValue meta = 4;
  }

  Body body = 1;
  Signature signature = 2;
}

message AddResponse {
  message Body {
    uint64 node_id = 1;
  }

  Body body = 1;
  Signature signature = 2;
};


message AddByPathRequest {
  message Body {
    bytes container_id = 1;
    string tree_id = 2;
    string path_attribute = 3;
    repeated string path = 4;
    repeated KeyValue meta = 5;
  }

  Body body = 1;
  Signature signature = 2;
}

message AddByPathResponse {
  message Body {
    repeated uint64 nodes = 1;
    uint64 parent_id = 2;
  }

  Body body = 1;
  Signature signature = 2;
};


message RemoveRequest {
  message Body {
    bytes container_id = 1;
    string tree_id = 2;
    uint64 node_id = 3;
  }

  Body body = 1;
  Signature signature = 2;
}

message RemoveResponse {
  message Body {
  }

  Body body = 1;
  Signature signature = 2;
};


message MoveRequest {
  message Body {
    // TODO import neo.fs.v2.refs.ContainerID directly.
    bytes container_id = 1;
    string tree_id = 2;
    uint64 parent_id = 3;
    uint64 node_id = 4;
    repeated KeyValue meta = 5;
  }

  Body body = 1;
  Signature signature = 2;
}

message MoveResponse {
  message Body {
  }

  Body body = 1;
  Signature signature = 2;
};


message GetNodeByPathRequest {
  message Body {
    bytes container_id = 1;
    string tree_id = 2;
    string path_attribute = 3;
    repeated string path = 4;
    repeated string attributes = 5;
    bool latest_only = 6;
    bool all_attributes = 7;
  }

  Body body = 1;
  Signature signature = 2;
}

message GetNodeByPathResponse {
  message Info {
    uint64 node_id = 1;
    uint64 timestamp = 2;
    repeated KeyValue meta = 3;
  }
  message Body {
    repeated Info nodes = 1;
  }

  Body body = 1;
  Signature signature = 2;
};


message GetSubTreeRequest {
  message Body {
    bytes container_id = 1;
    string tree_id = 2;
    uint64 root_id = 3;
    // Optional depth of the traversal. Zero means return only root.
    // Maximum depth is 10.
    uint32 depth = 4;
  }

  Body body = 1;
  Signature signature = 2;
}

message GetSubTreeResponse {
  message Body {
    uint64 node_id = 1;
    uint64 parent_id = 2;
    uint64 timestamp = 3;
    repeated KeyValue meta = 4;
  }

  Body body = 1;
  Signature signature = 2;
};


message ApplyRequest {
  message Body {
    bytes container_id = 1;
    string tree_id = 2;
    LogMove operation = 3;
  }

  Body body = 1;
  Signature signature = 2;
}

message ApplyResponse {
  message Body {
  }

  Body body = 1;
  Signature signature = 2;
};