// Copyright 2023 Google LLC
//
// 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 maps.fleetengine.delivery.v1;

import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/maps/fleetengine/delivery/v1/common.proto";
import "google/maps/fleetengine/delivery/v1/delivery_vehicles.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/timestamp.proto";

option csharp_namespace = "Google.Maps.FleetEngine.Delivery.V1";
option go_package = "cloud.google.com/go/maps/fleetengine/delivery/apiv1/deliverypb;deliverypb";
option java_multiple_files = true;
option java_outer_classname = "Tasks";
option java_package = "google.maps.fleetengine.delivery.v1";
option objc_class_prefix = "CFED";

// A Task in the Delivery API represents a single action to track. In general,
// there is a distinction between shipment-related Tasks and break Tasks. A
// shipment can have multiple Tasks associated with it. For example, there could
// be one Task for the pickup, and one for the drop-off or transfer. Also,
// different Tasks for a given shipment can be handled by different vehicles.
// For example, one vehicle could handle the pickup, driving the shipment to the
// hub, while another vehicle drives the same shipment from the hub to the
// drop-off location.
//
// Note: gRPC and REST APIs use different field naming conventions. For example,
// the `Task.journey_sharing_info` field in the gRPC API and the
// `DeliveryVehicle.journeySharingInfo` field in the REST API refer to the same
// field.
message Task {
  option (google.api.resource) = {
    type: "fleetengine.googleapis.com/Task"
    pattern: "providers/{provider}/tasks/{task}"
  };

  // The type of Task.
  enum Type {
    // Default, the Task type is unknown.
    TYPE_UNSPECIFIED = 0;

    // A pickup Task is the action taken for picking up a shipment from a
    // customer. Depot or feeder vehicle pickups should use the `SCHEDULED_STOP`
    // type.
    PICKUP = 1;

    // A delivery Task is the action taken for delivering a shipment to an end
    // customer. Depot or feeder vehicle dropoffs should use the
    // `SCHEDULED_STOP` type.
    DELIVERY = 2;

    // A scheduled stop Task is used for planning purposes. For example, it
    // could represent picking up or dropping off shipments from feeder vehicles
    // or depots. It shouldn't be used for any shipments that are picked up or
    // dropped off from an end customer.
    SCHEDULED_STOP = 3;

    // A Task that means the Vehicle is not available for service. For example,
    // this can happen when the driver takes a break, or when the vehicle
    // is being refueled.
    UNAVAILABLE = 4;
  }

  // The state of a Task. This indicates the Tasks's progress.
  enum State {
    // Default. Used for an unspecified or unrecognized Task state.
    STATE_UNSPECIFIED = 0;

    // Either the Task has not yet been assigned to a delivery vehicle, or the
    // delivery vehicle has not yet passed the `Task`'s assigned vehicle stop.
    OPEN = 1;

    // When the vehicle passes the vehicle stop for this Task.
    CLOSED = 2;
  }

  // The outcome of attempting to execute a Task. When `TaskState` is closed,
  // `TaskOutcome` indicates whether it was completed successfully.
  enum TaskOutcome {
    // The Task outcome before its value is set.
    TASK_OUTCOME_UNSPECIFIED = 0;

    // The Task completed successfully.
    SUCCEEDED = 1;

    // Either the Task couldn't be completed, or it was cancelled.
    FAILED = 2;
  }

  // The identity of the source that populated the `task_outcome_location`.
  enum TaskOutcomeLocationSource {
    // The task outcome before it is set.
    TASK_OUTCOME_LOCATION_SOURCE_UNSPECIFIED = 0;

    // The provider-specified the `task_outcome_location`.
    PROVIDER = 2;

    // The provider didn't specify the `task_outcome_location`, so Fleet Engine
    // used the last known vehicle location.
    LAST_VEHICLE_LOCATION = 3;
  }

  // Journey sharing specific fields.
  message JourneySharingInfo {
    // Tracking information for the stops that the assigned vehicle will make
    // before it completes this Task. Note that this list can contain stops
    // from other tasks.
    //
    // The first segment,
    // `Task.journey_sharing_info.remaining_vehicle_journey_segments[0]` (gRPC)
    // or `Task.journeySharingInfo.remainingVehicleJourneySegments[0]` (REST),
    // contains route information from the driver's last known location to the
    // upcoming `VehicleStop`. Current route information usually comes from the
    // driver app, except for some cases noted in the documentation for
    // [DeliveryVehicle.current_route_segment][maps.fleetengine.delivery.v1.DeliveryVehicle.current_route_segment].
    // The other segments in
    // `Task.journey_sharing_info.remaining_vehicle_journey_segments` (gRPC) or
    // `Task.journeySharingInfo.remainingVehicleJourneySegments` (REST) are
    // populated by Fleet Engine. They provide route information between the
    // remaining `VehicleStops`.
    repeated VehicleJourneySegment remaining_vehicle_journey_segments = 1;

    // Indicates the vehicle's last reported location of the assigned vehicle.
    DeliveryVehicleLocation last_location = 2;

    // Indicates whether the vehicle's lastLocation can be snapped to
    // the `current_route_segment`. This value is False if either
    // `last_location` or `current_route_segment` don't exist. This value is
    // computed by Fleet Engine. Updates from clients are ignored.
    bool last_location_snappable = 3;
  }

  // Must be in the format `providers/{provider}/tasks/{task}`.
  string name = 1;

  // Required. Immutable. Defines the type of the Task. For example, a break or
  // shipment.
  Type type = 2 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.field_behavior) = IMMUTABLE
  ];

  // Required. The current execution state of the Task.
  State state = 3 [(google.api.field_behavior) = REQUIRED];

  // The outcome of the Task.
  TaskOutcome task_outcome = 9;

  // The timestamp that indicates when the `Task`'s outcome was set by the
  // provider.
  google.protobuf.Timestamp task_outcome_time = 10;

  // The location where the `Task`'s outcome was set. This value is updated as
  // part of `UpdateTask`. If this value isn't explicitly updated by the
  // provider, then Fleet Engine populates it by default with the last known
  // vehicle location (the *raw* location).
  LocationInfo task_outcome_location = 11;

  // Indicates where the value of the `task_outcome_location` came from.
  TaskOutcomeLocationSource task_outcome_location_source = 12;

  // Immutable. This field facilitates the storing of an ID so you can avoid
  // using a complicated mapping. You cannot set `tracking_id` for Tasks of type
  // `UNAVAILABLE` and `SCHEDULED_STOP`. These IDs are subject to the
  // following restrictions:
  //
  // * Must be a valid Unicode string.
  // * Limited to a maximum length of 64 characters.
  // * Normalized according to [Unicode Normalization Form C]
  // (http://www.unicode.org/reports/tr15/).
  // * May not contain any of the following ASCII characters: '/', ':', '?',
  // ',', or '#'.
  string tracking_id = 4 [(google.api.field_behavior) = IMMUTABLE];

  // Output only. The ID of the vehicle that is executing this Task. Delivery
  // Vehicle IDs are subject to the following restrictions:
  //
  // * Must be a valid Unicode string.
  // * Limited to a maximum length of 64 characters.
  // * Normalized according to [Unicode Normalization Form C]
  // (http://www.unicode.org/reports/tr15/).
  // * May not contain any of the following ASCII characters: '/', ':', '?',
  // ',', or '#'.
  string delivery_vehicle_id = 5 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Immutable. The location where the Task will be completed.
  // Optional for `UNAVAILABLE` Tasks, but required for all other Tasks.
  LocationInfo planned_location = 6 [(google.api.field_behavior) = IMMUTABLE];

  // Required. Immutable. The time needed to execute a Task at this location.
  google.protobuf.Duration task_duration = 7 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.field_behavior) = IMMUTABLE
  ];

  // The time window during which the task should be completed.
  TimeWindow target_time_window = 14;

  // Output only. Journey sharing-specific fields. Not populated when state is
  // `CLOSED`.
  JourneySharingInfo journey_sharing_info = 8
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // The configuration for task tracking that specifies which data elements are
  // visible to the end users under what circumstances.
  TaskTrackingViewConfig task_tracking_view_config = 13;

  // A list of custom Task attributes. Each attribute must have a unique key.
  repeated TaskAttribute attributes = 15;
}

// The configuration message that defines when a data element of a Task should
// be visible to the end users.
message TaskTrackingViewConfig {
  // The option message that defines when a data element should be visible to
  // the end users.
  message VisibilityOption {
    // The specific visibility option chosen.
    oneof visibility_option {
      // This data element is visible to the end users if the remaining stop
      // count <= remaining_stop_count_threshold.
      int32 remaining_stop_count_threshold = 1;

      // This data element is visible to the end users if the ETA to the stop
      // <= duration_until_estimated_arrival_time_threshold.
      google.protobuf.Duration duration_until_estimated_arrival_time_threshold =
          2;

      // This data element is visible to the end users if the remaining
      // driving distance in meters <=
      // remaining_driving_distance_meters_threshold.
      int32 remaining_driving_distance_meters_threshold = 3;

      // If set to true, this data element is always visible to the end users
      // with no thresholds. This field cannot be set to false.
      bool always = 4;

      // If set to true, this data element is always hidden from the end users
      // with no thresholds. This field cannot be set to false.
      bool never = 5;
    }
  }

  // The field that specifies when route polyline points can be visible. If this
  // field is not specified, the project level default visibility configuration
  // for this data will be used.
  VisibilityOption route_polyline_points_visibility = 1;

  // The field that specifies when estimated arrival time can be visible. If
  // this field is not specified, the project level default visibility
  // configuration for this data will be used.
  VisibilityOption estimated_arrival_time_visibility = 2;

  // The field that specifies when estimated task completion time can be
  // visible. If this field is not specified, the project level default
  // visibility configuration for this data will be used.
  VisibilityOption estimated_task_completion_time_visibility = 3;

  // The field that specifies when remaining driving distance can be visible. If
  // this field is not specified, the project level default visibility
  // configuration for this data will be used.
  VisibilityOption remaining_driving_distance_visibility = 4;

  // The field that specifies when remaining stop count can be visible. If this
  // field is not specified, the project level default visibility configuration
  // for this data will be used.
  VisibilityOption remaining_stop_count_visibility = 5;

  // The field that specifies when vehicle location can be visible. If this
  // field is not specified, the project level default visibility configuration
  // for this data will be used.
  VisibilityOption vehicle_location_visibility = 6;
}
