// Copyright 2020 Enfonica Pty Ltd
//
// 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 enfonica.messaging.v1;

import "google/protobuf/timestamp.proto";
import "google/api/annotations.proto";
import "google/api/field_behavior.proto";
import "google/api/client.proto";
import "google/api/resource.proto";
import "google/type/money.proto";

option cc_enable_arenas = true;
option csharp_namespace = "Enfonica.Messaging.V1";
option go_package = "github.com/enfonica/enfonica-go/messaging/v1;messaging";
option java_multiple_files = true;
option java_outer_classname = "MessagesProto";
option java_package = "com.enfonica.messaging.v1";
option objc_class_prefix = "ENFON";

// Manages Messages.
// Messages can be SMS, whatsapp messages, etc.
service Messages {
  option (google.api.default_host) = "messaging.api.enfonica.com";
  option (google.api.oauth_scopes) =
      "https://api.enfonica.com/auth/messaging";

  // Creates a Message and queues it for sending.
  // Returns the created message.
  //
  // The caller must have `messaging.messages.create` permission on the project.
  rpc CreateMessage(CreateMessageRequest) returns (Message) {
    option (google.api.http) = {
      post: "/v1/{parent=projects/*}/messages"
      body: "message"
    };
    option (google.api.method_signature) = "parent,message";
  };

  // Retrieves a Message identified by the supplied resource name.
  //
  // The caller must have `messaging.messages.get` permission on the project.
  rpc GetMessage(GetMessageRequest) returns (Message) {
    option (google.api.http) = {
      get: "/v1/{name=projects/*/messages/*}"
    };
    option (google.api.method_signature) = "name";
  }

  // Lists the Messages of the specified project.
  // List returns Messages sorted by create_time descending.
  //
  // The caller must have `messaging.messages.list` permission on the project.
  rpc ListMessages(ListMessagesRequest) returns (ListMessagesResponse) {
    option (google.api.http) = {
      get: "/v1/{parent=projects/*}/messages"
    };
    option (google.api.method_signature) = "parent";
  }
}

// The Message resource. This represents a message, such as an SMS.
message Message {
  option (google.api.resource) = {
    type: "messaging.api.enfonica.com/Message"
    pattern: "projects/{project}/messages/{message}"
  };

  // The status of a message.
  // (-- api-linter: core::0216::synonyms=disabled
  //     aip.dev/not-precedent: `Status` is used instead of `State` in this package. --)
  enum Status {
    // Unspecified status.
    STATUS_UNSPECIFIED = 0;

    // The message has been queued for sending.
    QUEUED = 1;

    // The message is currently being dispatched to an upstream carrier.
    SENDING = 2;

    // The upstream carrier has accepted the message.
    SENT = 3;

    // The message failed to be sent within the Enfonica network.
    // For upstream failures, the status will be `UNDELIVERED`.
    FAILED = 4;

    // The upstream has confirmed message delivery, where available, to the
    // destination handset.
    DELIVERED = 5;

    // The upstream returned a delivery receipt indicating the message was not
    // delivered.
    UNDELIVERED = 6;

    // The message is an incoming message that has been received.
    RECEIVED = 7;
  }

  // The direction of a message.
  enum Direction {
    // Unspecified direction.
    DIRECTION_UNSPECIFIED = 0;

    // An outgoing message.
    OUTGOING = 1;

    // An incoming message
    INCOMING = 2;
  }

  // The type of message that this is.
  enum MessageClassification {
    // Unspecified.
    MESSAGE_CLASSIFICATION_UNSPECIFIED = 0;

    // The message is not classified. This message will be checked against unsubscribers
    // before being sent.
    UNCLASSIFIED = 1;

    // A transactional message. This message will not be checked against unsubscribers
    // before being sent.
    TRANSACTIONAL = 2;

    // A marketing message. This message will be checked against unsubscribers
    // before being sent.
    MARKETING = 3;
  }

  // Behaviour with regards to unsubscribe content within the message.
  enum UnsubscribeContentBehavior {
    // Unspecified.
    UNSUBSCRIBE_CONTENT_BEHAVIOR_UNSPECIFIED = 0;

    // Do not insert any unsubscribe content within the message.
    NONE = 1;

    // Append a short URL to the end of the message body which allows the user
    // to unsubscribe. This will only append the URL, and optionally a whitespace
    // character before the URL.
    //
    // Example `body` to use with this paramater:
    //
    // ```
    // "This is a marketing message. To unsubscribe:"
    // ```
    APPEND_URL = 2;
  }

  // The encoding of a message body.
  enum MessageEncoding {
    // Unknown message encoding.
    MESSAGE_ENCODING_UNSPECIFIED = 0;

    // GSM 7-bit encoding.
    GSM7 = 1;

    // UCS-2 encoding.
    UCS2 = 2;
  }

  // Resource name of the message. It must match the pattern `projects/*/messages/*`
  string name = 1;

  // The recipient phone number in +E164.
  // (-- api-linter: core::0140::prepositions=disabled
  //     aip.dev/not-precedent: Not a preposition. --)
  string to = 2 [(google.api.field_behavior) = REQUIRED];

  // The phone number in +E164 or alphanumeric sender ID that initiated the message.
  // (-- api-linter: core::0140::prepositions=disabled
  //     aip.dev/not-precedent: Not a preposition. --)
  // (-- api-linter: core::0140::reserved-words=disabled
  //     aip.dev/not-precedent: `from` is a core concept in Enfonica APIs. --)
  string from = 3 [(google.api.field_behavior) = REQUIRED];

  // The text of the message. Maximum of 1530 characters for messages encoding using GSM
  // 7-bit encoding and 670 characters for messages encoding using UCS2 encoding. If a
  // longer body is specified, it will be truncated to the maximum length.
  string body = 4;

  // The URL where [status updates webhooks](https://enfonica.com/docs/cloud-sms/webhooks/#message-status-update)
  // should be sent.
  // (-- api-linter: core::0140::uri=disabled
  //     aip.dev/not-precedent: url is used in this package. --)
  string status_update_url = 5;

  // The URL where replies, in the form of [incoming message webhooks](https://enfonica.com/docs/cloud-sms/webhooks/#incoming-message)
  // should be sent. This overrides any message handler URLs defined against the
  // phone number receiving the reply.
  // (-- api-linter: core::0140::uri=disabled
  //     aip.dev/not-precedent: url is used in this package. --)
  string reply_url = 6;

  // How long the message can stay in Enfonica's outgoing message queue, in seconds. Once the
  // message has been accepted by carriers, we cannot guarantee the message will not
  // be queued after this period.
  // (-- api-linter: core::0142::time-field-type=disabled
  //     aip.dev/not-precedent: Not a timestamp. --)
  int32 validity_period_seconds = 7;

  // Whether to automatically reply certain Unicode characters with similar GSM-7
  // characters.
  bool smart_encoding = 8;

  // You can store any arbitrary data against labels. The maximum key size is 100. The maximum
  // value size is 1000. The maximum number of keys is 50.
  map<string, string> labels = 20;

  // The type of message that this is, such as transactional or marketing.
  MessageClassification classification = 21;

  // Whether the `body` should be modified to include content indicatig how to unsubscribe.
  UnsubscribeContentBehavior unsubscribe_content_behavior = 22;

  // The direction of the message. Can be `outgoing` for messages that are sent or `incoming`
  // for messages that are received.
  Direction direction = 10 [(google.api.field_behavior) = OUTPUT_ONLY];

  // If the outgoing message failed to be delivered, the reason why.
  string error_code = 11 [(google.api.field_behavior) = OUTPUT_ONLY];

  // The human readable message associated with the error.
  string error_message = 12 [(google.api.field_behavior) = OUTPUT_ONLY];

  // The number of segments that make up the body.
  int32 segment_count = 13 [(google.api.field_behavior) = OUTPUT_ONLY];

  // The price of this message. This may not be populated until a certain stage in the message
  // lifecycle.
  google.type.Money price = 14 [(google.api.field_behavior) = OUTPUT_ONLY];

  // The current status of the message.
  // (-- api-linter: core::0216::synonyms=disabled
  //     aip.dev/not-precedent: `status` is used instead of `state` in this package. --)
  Status status = 15 [(google.api.field_behavior) = OUTPUT_ONLY];

  // The identity that created the message.  This may be your user or service account,
  // or identities used internally by Enfonica products.
  string create_identity = 16 [(google.api.field_behavior) = OUTPUT_ONLY];

  // The creation time of the message.
  google.protobuf.Timestamp create_time = 17 [(google.api.field_behavior) = OUTPUT_ONLY];

  // The time the message was sent. Only set for outgoing message.
  google.protobuf.Timestamp send_time = 18 [(google.api.field_behavior) = OUTPUT_ONLY];

  // The time when delivery was confirmed for the message. Only set for outgoing message.
  google.protobuf.Timestamp deliver_time = 19 [(google.api.field_behavior) = OUTPUT_ONLY];

  // The encoding used for the body.
  MessageEncoding encoding = 23 [(google.api.field_behavior) = OUTPUT_ONLY];
}

// Request to create a new message.
message CreateMessageRequest {
  // The resource name of the parent project to create the message under.
  // Must be of the form `projects/*`.
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "messaging.api.enfonica.com/Message"
    }
  ];

  // The message resource to be created.
  Message message = 2 [(google.api.field_behavior) = REQUIRED];
}

// The GetMessage request message.
message GetMessageRequest {
  // The resource name of the Message to retrieve.
  // Must be of the form `projects/*/messages/*`.
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "messaging.api.enfonica.com/Message"
    }
  ];
}

// The ListMessages request message.
message ListMessagesRequest {
  // The resource name of the parent of which to list messages.
  // Must be of the form `projects/*`.
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "messaging.api.enfonica.com/Message"
    }
  ];

  // The maximum number of Messages to return in the response.
  // Default value is 10 and maximum value is 100.
  int32 page_size = 2;

  // A pagination token returned from a previous call to `ListMessages`
  // that indicates where this listing should continue from.
  string page_token = 3;

  // The timestamp (inclusive) from which to retrieve messages. The
  // create_time of the Message is used.
  //
  // This field is deprecated. Use `filter` instead. If a value is specified for
  // both `start_time` and `filter`, the call will fail.
  //
  // (-- api-linter: core::0132::request-unknown-fields=disabled
  //     aip.dev/not-precedent: List has additional fields in this package. --)
  // (-- deprecated --)
  google.protobuf.Timestamp start_time = 4;

  // The timestamp (exclusive) until which to retrieve messages. The
  // create_time of the Message is used.
  //
  // This field is deprecated. Use `filter` instead. If a value is specified for
  // both `end_time` and `filter`, the call will fail.
  //
  // (-- api-linter: core::0132::request-unknown-fields=disabled
  //     aip.dev/not-precedent: List has additional fields in this package. --)
  // (-- deprecated --)
  google.protobuf.Timestamp end_time = 5;

  // Filter string to specify which results should be returned.
  //
  // The following fields can be filtered:
  // - `createTime`
  // - `to`
  // - `from`
  // - `status`
  // - `direction`
  // - `encoding`
  //
  // For example:
  // createTime >= '2021-01-01T06:00:00.0Z' AND createTime < '2021-02-01' AND
  // status = DELIVERED OR status = UNDELIVERED AND to = '+61*' OR from = '+61*'
  //
  // Note that OR has higher precendence than AND.
  string filter = 6;
}

// The ListMessages response message.
message ListMessagesResponse {
  // A possibly paginated list of Messages that are direct descendants of
  // the specified parent resource.
  repeated Message messages = 1;

  // If this is set, it indicates there are additional results and contains the
  // token to retrieve the next page of results. To use this, pass it in the
  // `page_token` field when calling `ListMessages`.
  string next_page_token = 2;
}
