// 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.voice.v1beta1;

import "google/protobuf/timestamp.proto";
import "google/protobuf/duration.proto";
import "google/api/annotations.proto";
import "google/type/money.proto";
import "google/api/resource.proto";
import "google/api/field_behavior.proto";
import "google/api/client.proto";
import "google/type/latlng.proto";
import "enfonica/voice/v1beta1/call_recording_config.proto";

option cc_enable_arenas = true;
option csharp_namespace = "Enfonica.Voice.V1Beta1";
option go_package = "github.com/enfonica/enfonica-go/voice/v1beta1;voice";
option java_multiple_files = true;
option java_outer_classname = "CallsProto";
option java_package = "com.enfonica.voice.v1beta1";
option objc_class_prefix = "ENFON";

// Manages Calls.
service Calls {
  option (google.api.default_host) = "voice.api.enfonica.com";
  option (google.api.oauth_scopes) =
      "https://api.enfonica.com/auth/voice";

  // Creates a call in the state QUEUED. This will cause an outgoing call
  // to be started.
  //
  // The caller must have `voice.calls.create` permission on the project.
  rpc CreateCall(CreateCallRequest) returns (Call) {
    option (google.api.http) = {
    post: "/v1beta1/{parent=projects/*}/calls"
      body: "call"
    };
    option (google.api.method_signature) = "parent,call";
  }

  // Retrieves a Call identified by the supplied resource name.
  //
  // The caller must have `voice.calls.get` permission on the project.
  rpc GetCall(GetCallRequest) returns (Call) {
    option (google.api.http) = {
      get: "/v1beta1/{name=projects/*/calls/*}"
    };
    option (google.api.method_signature) = "name";
  }

  // Lists the Calls of the specified project.
  // List returns Calls sorted by create_time descending.
  //
  // The caller must have `voice.calls.list` permission on the project.
  rpc ListCalls(ListCallsRequest) returns (ListCallsResponse) {
    option (google.api.http) = {
      get: "/v1beta1/{parent=projects/*}/calls"
    };
    option (google.api.method_signature) = "parent";
  }
}

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

  // Options that are applied to the call when it is an outgoing call created
  // by the API.
  message ApiCallOptions {
    // One or more URIs where VoiceML requests should be made to control the call.
    // The first URI will be attempted first, while the other URIs are only used
    // if the initial URI fails. Can be any supported URI.
    // Minimum 1 URI, maximum 5 URIs.
    repeated string handler_uris = 1 [(google.api.field_behavior) = REQUIRED];

    // The URL where state updates should be sent.
    string state_update_uri = 2;

    // The maximum amount of time, in seconds, the call is allowed to attempt an endpoint.
    // Default 30 seconds. Minimum 1, maximum 600 seconds.
    // (-- api-linter: core::0142::time-field-type=disabled
    //     aip.dev/not-precedent: This is not a timestamp. --)
    int32 timeout_seconds = 3;

    // The configuration of call recording. If not specified, no call recording
    // will be configured.
    CallRecordingConfig recording = 4;
  }

  // The state of a call.
  enum State {
    // Unspecified status.
    STATE_UNSPECIFIED = 0;

    // The call has been queued.
    QUEUED = 1;

    // The call is being attempted.
    STARTING = 2;

    // The remote party is ringing.
    RINGING = 3;

    // The call has been answered.
    IN_PROGRESS = 4;

    // The call was answered and is now finished.
    COMPLETED = 5;

    // The call could not be made.
    FAILED = 6;

    // The call was not answered. This is the same as the call waiting to
    // be answered and timing out.
    NOT_ANSWERED = 7;

    // The remote party indicated they were busy.
    BUSY = 8;
    
    // The call was not answered and it was actively rejected.
    REJECTED = 9;
  }

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

    // An outgoing call.
    OUTGOING = 1;

    // An incoming call
    INCOMING = 2;
  }

  // The transport of a call.
  enum Transport {
    // Unspecified transport.
    TRANSPORT_UNSPECIFIED = 0;

    // The call was transported over PSTN (Public Switched Telephone Network).
    PSTN = 1;

    // The call was transported over an Enfonica Client (WebRTC).
    CLIENT = 2;

    // The call was transported over SIP.
    SIP = 3;
  }

  // How a call was created.
  enum CreateMethod {
    // Unspecified create method.
    CREATE_METHOD_UNSPECIFIED = 0;

    // The call was created as a result of receiving an incoming call.
    INCOMING_CALL = 1;

    // The call was created by its parent call,
    // e.g. VoiceML `<Call>` or `<Redirect>`.
    PARENT_CALL = 2;

    // The call was creating using the API.
    API = 3;
  }

  // Resource name of the call. It is of the form `projects/*/calls/*`
  string name = 1;

  // The recipient of the call.
  //
  // For PSTN calls, this is the phone number in +E164 format.
  //
  // For calls to a SIP domain, this is the URI in the To header, in the format
  // `sip:user-or-number@domain`.
  //
  // When placing outgoing API calls, only PSTN is supported.
  // (-- api-linter: core::0140::prepositions=disabled
  //     aip.dev/not-precedent: Not a preposition. --)
  string to = 2 [(google.api.field_behavior) = REQUIRED];

  // The originator of the call.
  //
  // For PSTN calls, this is the CLI (Caller ID) in +E164 format. When placing
  // outgoing API calls, this is required.
  //
  // For calls to a SIP domain, this is the URI in the From header, in the
  // format `sip:user-or-number@domain`.
  //
  // This field will not be set if the CLI originated from the PSTN and
  // `is_private` is true.
  // (-- 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 approximate location where the call originated from. Only set for
  // INCOMING calls (this may be changed in the future).
  // (-- api-linter: core::0140::prepositions=disabled
  //     aip.dev/not-precedent: Not a preposition. --)
  NumberLocation from_location = 25;

  // The zone associated with the `from` phone number, if applicable. Only
  // applicable for PSTN. Only set for INCOMING calls (this may be changed in
  // the future).
  // (-- api-linter: core::0140::prepositions=disabled
  //     aip.dev/not-precedent: Not a preposition. --)
  string from_zone = 26;

  // Whether the Caller ID is private.
  bool is_private = 4;

  // You can store any arbitrary data against labels. The maximum number of keys is 50.
  // The maximum length of all keys and values combined is 10kB.
  map<string, string> labels = 8;

  // The transport that carried this call.
  Transport transport = 9 [(google.api.field_behavior) = OUTPUT_ONLY];

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

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

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

  // The price of this call. This may be set at various times. Generally,
  // it is available when the call reaches a terminal state, either immediately
  // or shortly afterwards.
  //
  // This price is the price of the call itself, and does not include charges
  // from the consumption of other paid services, such as text-to-speech and
  // transcription.
  google.type.Money price = 13 [(google.api.field_behavior) = OUTPUT_ONLY];

  // The current state of the call.
  State state = 14 [(google.api.field_behavior) = OUTPUT_ONLY];

  // The creation time of the call.
  // Output only.
  google.protobuf.Timestamp create_time = 16 [(google.api.field_behavior) = OUTPUT_ONLY];

  // The time the call was started.
  // For an incoming call, this is the same as `create_time`.
  // For an outgoing call, this is the time that the call attempt commenced.
  google.protobuf.Timestamp start_time = 17 [(google.api.field_behavior) = OUTPUT_ONLY];

  // The time the call started ringing. Only set for outgoing call.
  google.protobuf.Timestamp ring_time = 18 [(google.api.field_behavior) = OUTPUT_ONLY];

  // The time the call was answered.
  google.protobuf.Timestamp answer_time = 19 [(google.api.field_behavior) = OUTPUT_ONLY];

  // The time the call finished.
  google.protobuf.Timestamp end_time = 20 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Was the call bridged with another call at any point?
  bool bridged = 21 [(google.api.field_behavior) = OUTPUT_ONLY];

  // The name of the call that originated this call, set
  // for outgoing calls that were created during the execution of another call,
  // of the form `projects/*/calls/*`.
  string originating_call = 22 [(google.api.field_behavior) = OUTPUT_ONLY];

  // How this call started.
  CreateMethod create_method = 23 [(google.api.field_behavior) = OUTPUT_ONLY];

  // The options to use to handle this call. This is only required when a call is created
  // using the API.
  ApiCallOptions options = 24 [(google.api.field_behavior) = REQUIRED];

  // The `Call-ID` header of the call. Only set when transport is SIP.
  string sip_call_id = 27 [(google.api.field_behavior) = OUTPUT_ONLY];

  // The duration for which the call was answered. If the call was not answered
  // or it has not reached a terminal state, this field will not be set.
  google.protobuf.Duration answer_duration = 28 [(google.api.field_behavior) = OUTPUT_ONLY];
}

// Location information for a phone number.
message NumberLocation {
  // CLDR region code of the country/region. See http://cldr.unicode.org/ and
  // http://www.unicode.org/cldr/charts/30/supplemental/territory_information.html
  // for details. Example: "AU" for Australia.
  string region_code = 1;

  // If known, the highest administrative subdivision of a country or region.
  // For example, this can be a state, a territory, a province, an oblast, or a
  // prefecture.
  string administrative_area = 2;

  // If known, the locality associated with the phone number.
  // Generally refers to the city/town portion of the address.
  // Examples: AU suburb, US city, IT comune, UK post town.
  string locality = 3;

  // If known, the approximate coordinates of the location.
  google.type.LatLng coordinates = 4;
}

// Request to create a new call.
message CreateCallRequest {
  // The project under which to create the call in the form `projects/*`.
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "voice.api.enfonica.com/Call"
    }
  ];

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

// The GetCall request call.
message GetCallRequest {
  // The resource name of the Call to retrieve.
  // Must be of the form `projects/*/calls/*`.
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "voice.api.enfonica.com/Call"
    }
  ];
}

// The ListCalls request call.
message ListCallsRequest {
  // The resource name of the parent of which to list calls.
  // Must be of the form `projects/*`.
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "voice.api.enfonica.com/Call"
    }
  ];

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

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

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

// The ListCalls response call.
message ListCallsResponse {
  // A possibly paginated list of Calls that are direct descendants of
  // the specified parent resource.
  repeated Call calls = 1;

  // A pagination token returned from a previous call to `ListCalls`
  // that indicates from where listing should continue.
  string next_page_token = 2;
}
