/**
 *
 * Wechaty Puppet gRPC Protocol Buffers
 *  https://github.com/wechaty/grpc/
 *  Huan LI <zixia@zixia.net>
 *  Apr 2018
 *  License: Apache-2.0
 *
 * Google Protocol Buffers
 *  Style Guide - https://developers.google.com/protocol-buffers/docs/style
 *
 */
syntax = "proto3";
package wechaty;

import "google/api/annotations.proto";
import "protoc-gen-openapiv2/options/annotations.proto";

import "wechaty/deprecated/file-box.proto";

import "wechaty/puppet/base.proto";
import "wechaty/puppet/contact.proto";
import "wechaty/puppet/download-upload.proto";
import "wechaty/puppet/event.proto";
import "wechaty/puppet/friendship.proto";
import "wechaty/puppet/message.proto";
import "wechaty/puppet/room-invitation.proto";
import "wechaty/puppet/room-member.proto";
import "wechaty/puppet/room.proto";
import "wechaty/puppet/tag.proto";

option java_package="io.github.wechaty.grpc";
option go_package="github.com/wechaty/go-grpc/wechaty";

option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
  info: {
      title: "Wechaty Puppet Service OpenAPI Specification"
      description: "Wechaty is a Conversational RPA SDK for chatbot makers. With only 6 lines of code, you can create a bot on the most popular IMs like WeChat, Whatsapp, WeCom, Gitter, etc.\n\nWechaty Puppet Service is the RESTful API for Wechaty API, which is build on top of the Wechaty Puppet Abstraction and the gRPC proto definition."
      license: {
        name: "Apache-2.0"
        url: "http://www.apache.org/licenses/LICENSE-2.0.html"
      }
      contact: {
          name: "Wechaty"
          url: "https://github.com/wechaty/openapi"
          email: "wechaty@chatie.io"
      }
      version: "0.0.0"  // MUST be 0.0.0 at here: will be synced with the Git Repo when generating.
  }
  // schemes: [HTTP,HTTPS,WS,WSS]
  consumes: "application/json"
  produces: "application/json"
  responses: {
      key: "default"
      value: {
          description: ""
          schema: {
              json_schema: {
                  ref: ".google.rpc.Status"
              }
          }
      }
  }
};

service Puppet {
  /**
   * Deprecated: will be removed after Dec 31, 2022
   */
  rpc MessageFileStream     (puppet.MessageFileStreamRequest)             returns (stream puppet.MessageFileStreamResponse)   {}
  rpc MessageImageStream    (puppet.MessageImageStreamRequest)            returns (stream puppet.MessageImageStreamResponse)  {}
  rpc MessageSendFileStream (stream puppet.MessageSendFileStreamRequest)  returns (puppet.MessageSendFileStreamResponse)      {}

  /**
   *
   * Base
   *
   */
  rpc Start (puppet.StartRequest)  returns (puppet.StartResponse) {
    option (google.api.http) = {
      put: "/start"
    };
  }
  rpc Stop (puppet.StopRequest)    returns (puppet.StopResponse) {
    option (google.api.http) = {
      put: "/stop"
    };
  }

  rpc Logout (puppet.LogoutRequest)      returns (puppet.LogoutResponse) {
    option (google.api.http) = {
      put: "/logout"
    };
  }
  rpc Ding (puppet.DingRequest)          returns (puppet.DingResponse) {
    option (google.api.http) = {
      post: "/ding"
      body: "*"
    };
  }
  rpc Version (puppet.VersionRequest)    returns (puppet.VersionResponse) {
    option (google.api.http) = {
      get: "/version"
    };
  }

  /**
   *
   * Event - Server Stream
   *
   */
  rpc Event (puppet.EventRequest)  returns (stream puppet.EventResponse) {
    option (google.api.http) = {
      get: "/events"
    };
  }

  rpc DirtyPayload (puppet.DirtyPayloadRequest) returns (puppet.DirtyPayloadResponse) {
    option (google.api.http) = {
      additional_bindings {
        put: "/message/{id}/dirty/{type=PAYLOAD_TYPE_MESSAGE}"
      }
      additional_bindings {
        put: "/contacts/{id}/dirty/{type=PAYLOAD_TYPE_CONTACT}"
      }
      additional_bindings {
        put: "/rooms/{id}/dirty/{type=PAYLOAD_TYPE_ROOM}"
      }
      additional_bindings {
        put: "/rooms/{id}/dirty/members/{type=PAYLOAD_TYPE_ROOM_MEMBER}"
      }
      additional_bindings {
        put: "/friendships/{id}/dirty/{type=PAYLOAD_TYPE_FRIENDSHIP}"
      }
    };
  }

  /**
   *
   * Contact Self
   *
   */
  rpc ContactSelfQRCode (puppet.ContactSelfQRCodeRequest) returns (puppet.ContactSelfQRCodeResponse) {
    option (google.api.http) = {
      get: "/contacts/self/qrcode"
    };

  }
  rpc ContactSelfName (puppet.ContactSelfNameRequest) returns (puppet.ContactSelfNameResponse) {
    option (google.api.http) = {
      put: "/contacts/self/name/{name}"
    };
  }
  rpc ContactSelfSignature (puppet.ContactSelfSignatureRequest) returns (puppet.ContactSelfSignatureResponse) {
    option (google.api.http) = {
      put: "/contacts/self/signature"
      body: "*"
    };
  }

  /**
   *
   * Contact
   *
   */
  rpc ContactPayload (puppet.ContactPayloadRequest)  returns (puppet.ContactPayloadResponse) {
    option (google.api.http) = {
      get: "/contacts/{id}"
    };

    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: 'Get a contact payload';
      operation_id: 'contactPayload';
      tags: "contact";
      responses: {
        key: "200"
          value: {
          description: "Contact payload";
        }
      }
    };
  }

  rpc ContactAlias (puppet.ContactAliasRequest) returns (puppet.ContactAliasResponse) {
    option (google.api.http) = {
      put: "/contacts/{id}/alias"
      body: "*"
    };
  }
  rpc ContactAvatar (puppet.ContactAvatarRequest) returns (puppet.ContactAvatarResponse) {
    option (google.api.http) = {
      get: "/contacts/{id}/avatar" // TODO: Huan(202002) disable the avatar query parameters
      // additional_bindings {
      //   put: "/contacts/{id}/avatar"
      //   body: "*"
      // }
    };
  }
  rpc ContactPhone (puppet.ContactPhoneRequest) returns (puppet.ContactPhoneResponse) {
    option (google.api.http) = {
      put: "/contacts/{contact_id}/phone"
      body: "*"
    };

  }
  rpc ContactCorporationRemark (puppet.ContactCorporationRemarkRequest) returns (puppet.ContactCorporationRemarkResponse) {
    option (google.api.http) = {
      put: "/contacts/{contact_id}/corporation-remark"
      body: "*"
    };
  }
  rpc ContactDescription (puppet.ContactDescriptionRequest) returns (puppet.ContactDescriptionResponse) {
    option (google.api.http) = {
      put: "/contacts/{contact_id}/description"
      body: "*"
    };
  }

  /**
   * Huan(202002): consider changing response to a stream in the future for better performance
   */
  rpc ContactList (puppet.ContactListRequest) returns (puppet.ContactListResponse) {
    option (google.api.http) = {
      get: "/contacts"
    };
  }

  /**
   *
   * Friendship
   *
   */
  rpc FriendshipPayload (puppet.FriendshipPayloadRequest)  returns (puppet.FriendshipPayloadResponse) {
    option (google.api.http) = {
      get: "/friendship/{id}"
    };
  }

  rpc FriendshipSearchPhone (puppet.FriendshipSearchPhoneRequest) returns (puppet.FriendshipSearchPhoneResponse) {
    option (google.api.http) = {
      get: "/friendship/search/phone/{phone}"
    };
  }
  rpc FriendshipSearchWeixin (puppet.FriendshipSearchWeixinRequest) returns (puppet.FriendshipSearchWeixinResponse) {
    option (google.api.http) = {
      get: "/friendship/search/weixin/{weixin}"
    };
  }

  rpc FriendshipAdd (puppet.FriendshipAddRequest) returns (puppet.FriendshipAddResponse) {
    option (google.api.http) = {
      put: "/friendship/add/{contact_id}"
      body: "*"
    };
  }
  rpc FriendshipAccept (puppet.FriendshipAcceptRequest) returns (puppet.FriendshipAcceptResponse) {
    option (google.api.http) = {
      put: "/friendship/accept/{id}"
    };
  }

  /**
   *
   * Message
   *
   */

  rpc MessageFile (puppet.MessageFileRequest) returns (puppet.MessageFileResponse) {
  }

  rpc MessageImage (puppet.MessageImageRequest) returns (puppet.MessageImageResponse) {
  }

  rpc MessageSendFile (puppet.MessageSendFileRequest) returns (puppet.MessageSendFileResponse) {
  }

  rpc MessagePayload (puppet.MessagePayloadRequest)  returns (puppet.MessagePayloadResponse) {
    option (google.api.http) = {
      get: "/message/{id}"
    };
  }

  rpc MessageContact (puppet.MessageContactRequest) returns (puppet.MessageContactResponse) {
    option (google.api.http) = {
      get: "/message/{id}/contact"
    };
  }
  rpc MessageMiniProgram (puppet.MessageMiniProgramRequest) returns (puppet.MessageMiniProgramResponse) {
    option (google.api.http) = {
      get: "/message/{id}/mini-program"
    };
  }
  rpc MessageUrl (puppet.MessageUrlRequest) returns (puppet.MessageUrlResponse) {
    option (google.api.http) = {
      get: "/message/{id}/url-link"
    };
  }
  rpc MessageRecall (puppet.MessageRecallRequest) returns (puppet.MessageRecallResponse) {
    option (google.api.http) = {
      put: "/message/{id}/recall"
    };
  }
  rpc MessageForward (puppet.MessageForwardRequest) returns (puppet.MessageForwardResponse) {
    option (google.api.http) = {
      post: "/messages/{message_id}/forward/{conversation_id}"
      additional_bindings {
        post: "/conversations/{conversation_id}/forward/{message_id}"
      }
    };
  }
  rpc MessageLocation (puppet.MessageLocationRequest) returns (puppet.MessageLocationResponse) {
    option (google.api.http) = {
      get: "/message/{id}/location"
    };
  }

  rpc MessageSendContact (puppet.MessageSendContactRequest) returns (puppet.MessageSendContactResponse) {
    option (google.api.http) = {
      post: "/conversations/{conversation_id}/contact"
      body: "*"
    };
  }
  rpc MessageSendText (puppet.MessageSendTextRequest) returns (puppet.MessageSendTextResponse) {
    option (google.api.http) = {
      post: "/conversations/{conversation_id}/text"
      body: "*"
    };
  }
  rpc MessageSendMiniProgram (puppet.MessageSendMiniProgramRequest) returns (puppet.MessageSendMiniProgramResponse) {
    option (google.api.http) = {
      post: "/conversations/{conversation_id}/mini-program"
      body: "*"
    };
  }
  rpc MessageSendUrl (puppet.MessageSendUrlRequest) returns (puppet.MessageSendUrlResponse) {
    option (google.api.http) = {
      post: "/conversations/{conversation_id}/url-link"
      body: "*"
    };
  }
  rpc MessageSendLocation (puppet.MessageSendLocationRequest) returns (puppet.MessageSendLocationResponse) {
    option (google.api.http) = {
      post: "/conversations/{conversation_id}/location"
      body: "*"
    };
  }

  /**
   *
   * Room
   *
   */
  rpc RoomPayload (puppet.RoomPayloadRequest) returns (puppet.RoomPayloadResponse) {
    option (google.api.http) = {
      get: "/rooms/{id}"
    };
  }

  rpc RoomList (puppet.RoomListRequest) returns (puppet.RoomListResponse) {
    option (google.api.http) = {
      get: "/rooms"
    };
  }

  rpc RoomAdd (puppet.RoomAddRequest) returns (puppet.RoomAddResponse) {
    option (google.api.http) = {
      put: "/rooms/{id}/add/{contact_id}"
    };
  }
  rpc RoomAvatar (puppet.RoomAvatarRequest) returns (puppet.RoomAvatarResponse) {
    option (google.api.http) = {
      get: "/rooms/{id}/avatar"
    };
  }
  rpc RoomCreate (puppet.RoomCreateRequest) returns (puppet.RoomCreateResponse) {
    option (google.api.http) = {
      post: "/rooms"
      body: "*"
    };
  }
  rpc RoomDel (puppet.RoomDelRequest) returns (puppet.RoomDelResponse) {
    option (google.api.http) = {
      delete: "/rooms/{id}/member/{contact_id}"
    };
  }
  rpc RoomQuit (puppet.RoomQuitRequest) returns (puppet.RoomQuitResponse) {
    option (google.api.http) = {
      delete: "/rooms/{id}"
    };
  }

  rpc RoomTopic (puppet.RoomTopicRequest) returns (puppet.RoomTopicResponse) {
    option (google.api.http) = {
      get: "/rooms/{id}/topic"
    };
  }
  rpc RoomQRCode (puppet.RoomQRCodeRequest) returns (puppet.RoomQRCodeResponse) {
    option (google.api.http) = {
      get: "/rooms/{id}/qrcode"
    };
  }
  rpc RoomAnnounce (puppet.RoomAnnounceRequest) returns (puppet.RoomAnnounceResponse) {
    option (google.api.http) = {
      get: "/rooms/{id}/announcement"  // TODO: disable other get parameters
      additional_bindings {
        put: "/rooms/{id}/announcement"
        body: "*"
      }
    };
  }

  /**
   *
   * Room Member
   *
   */
  rpc RoomMemberPayload (puppet.RoomMemberPayloadRequest) returns (puppet.RoomMemberPayloadResponse) {
    option (google.api.http) = {
      get: "/rooms/{id}/members/{member_id}"
    };
  }

  rpc RoomMemberList (puppet.RoomMemberListRequest) returns (puppet.RoomMemberListResponse) {
    option (google.api.http) = {
      get: "/rooms/{id}/members"
    };
  }

  /**
   *
   * Room Invitation
   *
   */
  rpc RoomInvitationPayload (puppet.RoomInvitationPayloadRequest)  returns (puppet.RoomInvitationPayloadResponse) {
    option (google.api.http) = {
      get: "/room-invitations/{id}"
    };
  }
  rpc RoomInvitationAccept (puppet.RoomInvitationAcceptRequest) returns (puppet.RoomInvitationAcceptResponse) {
    option (google.api.http) = {
      put: "/room-invitations/{id}/accept"
    };
  }

  /**
   *
   * Tag
   *
   */
  rpc TagContactAdd (puppet.TagContactAddRequest) returns (puppet.TagContactAddResponse) {
    option (google.api.http) = {
      put: "/contacts/{contact_id}/tags/{id}"
    };
  }
  rpc TagContactRemove (puppet.TagContactRemoveRequest) returns (puppet.TagContactRemoveResponse) {
    option (google.api.http) = {
      delete: "/contacts/{contact_id}/tags/{id}"
    };
  }

  /**
   * Operate Sub-Collections
   *   https://cloud.google.com/apis/design/design_patterns#list_sub-collections
   */
  rpc TagContactDelete (puppet.TagContactDeleteRequest) returns (puppet.TagContactDeleteResponse) {
    option (google.api.http) = {
      delete: "/contacts/-/tags/{id}"
    };
  }

   rpc TagContactList (puppet.TagContactListRequest) returns (puppet.TagContactListResponse) {
    option (google.api.http) = {
      get: "/contacts/{contact_id}/tags"
    };
  }

  /**
   * File/Blob download & upload
   */
  rpc Download (puppet.DownloadRequest) returns (stream puppet.DownloadResponse) {
    option (google.api.http) = {
      get: "/download/{id}"
    };
  }
  rpc Upload (stream puppet.UploadRequest) returns (puppet.UploadResponse) {
    option (google.api.http) = {
      post: "/upload"
      body: "*"
    };
  }

}
