/*
 *     Copyright 2022 The Dragonfly Authors
 *
 * 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";

package scheduler.v2;

import "common.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/timestamp.proto";

// RegisterPeerRequest represents peer registered request of AnnouncePeerRequest.
message RegisterPeerRequest {
  // Download information.
  common.v2.Download download = 1;
}

// RegisterSeedPeerRequest represents seed peer registered request of AnnouncePeerRequest.
message RegisterSeedPeerRequest {
  // Download information.
  common.v2.Download download = 1;
}

// DownloadPeerStartedRequest represents peer download started request of AnnouncePeerRequest.
message DownloadPeerStartedRequest {
}

// DownloadPeerBackToSourceStartedRequest represents peer download back-to-source started request of AnnouncePeerRequest.
message DownloadPeerBackToSourceStartedRequest {
  // The description of the back-to-source reason.
  string description = 1;
}

// DownloadPeerFinishedRequest represents peer download finished request of AnnouncePeerRequest.
message DownloadPeerFinishedRequest {
  // Total content length.
  int64 content_length = 1;
  // Total piece count.
  int32 piece_count = 2;
}

// DownloadPeerBackToSourceFinishedRequest represents peer download back-to-source finished request of AnnouncePeerRequest.
message DownloadPeerBackToSourceFinishedRequest {
  // Total content length.
  int64 content_length = 1;
  // Total piece count.
  int32 piece_count = 2;
}

// DownloadPeerFailedRequest represents peer download failed request of AnnouncePeerRequest.
message DownloadPeerFailedRequest {
  // The description of the download failed.
  string description = 1;
}

// DownloadPeerBackToSourceFailedRequest represents peer download back-to-source failed request of AnnouncePeerRequest.
message DownloadPeerBackToSourceFailedRequest {
  // The description of the download back-to-source failed.
  string description = 1;
}

// DownloadPieceFinishedRequest represents piece download finished request of AnnouncePeerRequest.
message DownloadPieceFinishedRequest {
  // Piece info.
  common.v2.Piece piece = 1;
}

// DownloadPieceBackToSourceFinishedRequest represents piece download back-to-source finished request of AnnouncePeerRequest.
message DownloadPieceBackToSourceFinishedRequest {
  // Piece info.
  common.v2.Piece piece = 1;
}

// DownloadPieceFailedRequest downloads piece failed request of AnnouncePeerRequest.
message DownloadPieceFailedRequest {
  // Piece info.
  common.v2.Piece piece = 1;
  // Temporary indicates whether the error is temporary.
  bool temporary = 2;
}

// HTTPResponse represents http protocol response of DownloadPieceBackToSourceFailedRequest.
message HTTPResponse {
  // HTTP Response Header.
  map<string, string> header = 1;
  // HTTP Status Code.
  int32 status_code = 2;
  // HTTP Status.
  string status = 3;
}

// HDFSResponse represents hdfs protocol response of DownloadPieceBackToSourceFailedRequest.
message HDFSResponse {
}

// S3Response represents s3 protocol response of DownloadPieceBackToSourceFailedRequest.
message S3Response {
}

// OSSResponse represents oss protocol response of DownloadPieceBackToSourceFailedRequest.
message OSSResponse {
}

// DownloadPieceBackToSourceFailedRequest downloads piece back-to-source failed request of AnnouncePeerRequest.
message DownloadPieceBackToSourceFailedRequest {
  // Piece info.
  common.v2.Piece piece = 1;

  oneof response {
    HTTPResponse http_response = 2;
    HDFSResponse hdfs_response = 3;
    S3Response s3_response = 4;
    OSSResponse oss_response = 5;
  }
}

// SyncPiecesFailedRequest syncs pieces failed request of AnnouncePeerRequest.
message SyncPiecesFailedRequest {
	// Parent peer id.
  string parent_id = 1;
  // The description of the error.
  string description = 2;
}

// AnnouncePeerRequest represents request of AnnouncePeer.
message AnnouncePeerRequest {
  // Host id.
  string host_id = 1;
  // Task id.
  string task_id = 2;
  // Peer id.
  string peer_id = 3;

  oneof request {
    RegisterPeerRequest register_peer_request = 4;
    RegisterSeedPeerRequest register_seed_peer_request = 5;
    DownloadPeerStartedRequest download_peer_started_request = 6;
    DownloadPeerBackToSourceStartedRequest download_peer_back_to_source_started_request = 7;
    DownloadPeerFinishedRequest download_peer_finished_request = 8;
    DownloadPeerBackToSourceFinishedRequest download_peer_back_to_source_finished_request = 9;
    DownloadPeerFailedRequest download_peer_failed_request = 10;
    DownloadPeerBackToSourceFailedRequest download_peer_back_to_source_failed_request = 11;
    DownloadPieceFinishedRequest download_piece_finished_request = 12;
    DownloadPieceBackToSourceFinishedRequest download_piece_back_to_source_finished_request = 13;
    DownloadPieceFailedRequest download_piece_failed_request = 14;
    DownloadPieceBackToSourceFailedRequest download_piece_back_to_source_failed_request = 15;
    SyncPiecesFailedRequest sync_pieces_failed_request = 16;
  }
}

// EmptyTaskResponse represents empty task response of AnnouncePeerResponse.
message EmptyTaskResponse {
}

// TinyTaskResponse represents tiny task response of AnnouncePeerResponse.
message TinyTaskResponse {
  // Tiny task content.
  bytes content = 1;
}

// SmallTaskResponse represents small task response of AnnouncePeerResponse.
message SmallTaskResponse {
  // TODO Fix clippy lint PR into new version.
  // The version of tonic needs to be upgraded,
  // refer to https://github.com/hyperium/tonic/pull/1181.
  // 
  // Candidate parent.
  // common.Peer candidate_parent = 1;
}

// NormalTaskResponse represents normal task response of AnnouncePeerResponse.
message NormalTaskResponse {
  // Candidate parents.
  repeated common.v2.Peer candidate_parents = 1;
  // Concurrent downloading piece count from the peers.
  int32 concurrent_piece_count = 2;
}

// NeedBackToSourceResponse represents need back-to-source response of AnnouncePeerResponse.
message NeedBackToSourceResponse {
  // The description of the back-to-source reason.
  string description = 1;
}

// AnnouncePeerResponse represents response of AnnouncePeer.
message AnnouncePeerResponse {
  oneof response {
    EmptyTaskResponse empty_task_response = 1;
    TinyTaskResponse tiny_task_response = 2;
    SmallTaskResponse small_task_response = 3;
    NormalTaskResponse normal_task_response = 4;
    NeedBackToSourceResponse need_back_to_source_response = 5;
  }
}

// StatPeerRequest represents request of StatPeer.
message StatPeerRequest {
  // Host id.
  string host_id = 1;
  // Task id.
  string task_id = 2;
  // Peer id.
  string peer_id = 3;
}

// TODO exchange peer request definition.
// ExchangePeerRequest represents request of ExchangePeer.
message ExchangePeerRequest {
  // Host id.
  string host_id = 1;
  // Task id.
  string task_id = 2;
  // Peer id.
  string peer_id = 3;
}

// TODO exchange peer response definition.
// ExchangePeerResponse represents response of ExchangePeer.
message ExchangePeerResponse {
}

// LeavePeerRequest represents request of LeavePeer.
message LeavePeerRequest {
  // Host id.
  string host_id = 1;
  // Task id.
  string task_id = 2;
  // Peer id.
  string peer_id = 3;
}

// StatTaskRequest represents request of StatTask.
message StatTaskRequest {
  // Task id.
  string id = 1;
}

// AnnounceHostRequest represents request of AnnounceHost.
message AnnounceHostRequest {
  // Host information.
  common.v2.Host host = 1;
}

// LeaveHostRequest represents request of LeaveHost.
message LeaveHostRequest{
  // Host id.
  string id = 1;
}

// ProbeStartedRequest represents started request of SyncProbesRequest.
message ProbeStartedRequest {
}

// Probe information.
message Probe {
  // Destination host metadata.
  common.v2.Host host = 1;
  // RTT is the round-trip time sent via this pinger.
  google.protobuf.Duration rtt = 2;
  // Probe create time.
  google.protobuf.Timestamp created_at = 3;
}

// ProbeFinishedRequest represents finished request of SyncProbesRequest.
message ProbeFinishedRequest {
  // Probes information.
  repeated Probe probes = 1;
}

// FailedProbe information.
message FailedProbe {
  // Destination host metadata.
  common.v2.Host host = 1;
  // The description of probing failed.
  string description = 2;
}

// ProbeFailedRequest represents failed request of SyncProbesRequest.
message ProbeFailedRequest {
  // Failed probes information.
  repeated FailedProbe probes = 1;
}

// SyncProbesRequest represents request of SyncProbes.
message SyncProbesRequest {
  // Source host metadata.
  common.v2.Host host = 1;

  oneof request {
    ProbeStartedRequest probe_started_request = 2;
    ProbeFinishedRequest probe_finished_request = 3;
    ProbeFailedRequest probe_failed_request = 4;
  }
}

// SyncProbesResponse represents response of SyncProbes.
message SyncProbesResponse {
  // Hosts needs to be probed.
  repeated common.v2.Host hosts = 1;
}

// Scheduler RPC Service.
service Scheduler{
  // AnnouncePeer announces peer to scheduler.
  rpc AnnouncePeer(stream AnnouncePeerRequest) returns(stream AnnouncePeerResponse);

  // Checks information of peer.
  rpc StatPeer(StatPeerRequest)returns(common.v2.Peer);

  // LeavePeer releases peer in scheduler.
  rpc LeavePeer(LeavePeerRequest)returns(google.protobuf.Empty);

  // TODO exchange peer api definition.
  // ExchangePeer exchanges peer information.
  rpc ExchangePeer(ExchangePeerRequest)returns(ExchangePeerResponse);

  // Checks information of task.
  rpc StatTask(StatTaskRequest)returns(common.v2.Task);

  // AnnounceHost announces host to scheduler.
  rpc AnnounceHost(AnnounceHostRequest)returns(google.protobuf.Empty);

  // LeaveHost releases host in scheduler.
  rpc LeaveHost(LeaveHostRequest)returns(google.protobuf.Empty);

  // SyncProbes sync probes of the host.
  rpc SyncProbes(stream SyncProbesRequest)returns(stream SyncProbesResponse);
}
