syntax = "proto3";

import "Modes.proto";
import "DirectionType.proto";

package planner.model;

option java_multiple_files = true;

message RoutingError {
  string message = 1;
  string code = 2;
}

message PlanResult {
  repeated TripPattern trips = 1;
  string timestamp = 2;
  /* Source cursor; the public request does not currently accept pagination cursors. */
  optional string previousPageCursor = 3;
  /* Source cursor; the public request does not currently accept pagination cursors. */
  optional string nextPageCursor = 4;
  repeated RoutingError errors = 5;
  int32 planner = 6; // Internal adapter identifier; not a passenger-facing name.
  optional bool containsOnDemand = 7;
  optional bool containsWithSurcharge = 8;

  /* Compared to a default plan request which modifications were made to the request such that the result was different */
  repeated string modifiers = 9;
  /* What is the "quality" of this result compared to the default plan request, higher is better */
  double grade = 10;
}

// Represents a Trip with multiple attributes and associated Legs.
message TripPattern {
  string expectedStartTime = 1; // ISO 8601 format
  string aimedStartTime = 2;   // ISO 8601 format
  string aimedEndTime = 3;     // ISO 8601 format
  string expectedEndTime = 4;  // ISO 8601 format
  int32 duration = 5;          // Duration in minutes
  int32 transfers = 6;         // Number of transfers
  optional int32 waitingTime = 7;       // Waiting time in minutes
  optional int32 walkTime = 8;          // Walking time in minutes
  optional double streetDistance = 9;   // Street distance in meters
  optional double distance = 10;        // Total distance in meters
  repeated string systemNotices = 11; // List of notices or messages
  repeated Leg legs = 12;      // Details about individual legs of the trip
  string id = 13;              // Source-derived trip identity; not guaranteed unique across service dates/departures. Use itineraryHash for targeted replay.

  optional PricingInformation pricingInfo = 14; // Pricing information for the trip

  optional string itineraryHash = 15; // Opaque transit/flex replay hash: v1:<sorted modifier IDs>#<base64url 96-bit SHA-256 prefix>. Empty for purely non-transit trips

  double grade = 16; // Request-aware quality of this trip inside its result, higher is better
}

// One timeline segment: transit, non-transit, waiting or flexible.
message Leg {
  string aimedStartTime = 1;   // ISO 8601 format
  string aimedEndTime = 2;     // ISO 8601 format
  optional string expectedStartTime = 3;// ISO 8601 format
  optional string expectedEndTime = 4;  // ISO 8601 format
  int32 duration = 6;          // Duration in minutes
  double distance = 7;         // Distance of the leg in meters
  PointsOnLink pointsOnLink = 8; // Polyline points representing the leg

  oneof leg_type {
    TransitLeg transitLeg = 10; // Transit-specific leg details
    NonTransitLeg nonTransitLeg = 11; // Non-transit-specific leg details
    WaitingLeg waitingLeg = 13; // Waiting-specific leg details
    FlexibleLeg flexibleLeg = 14; // Flexible (on-demand) transit leg details
  }

  string id = 12;              // Unique identifier for the leg
}

// Represents a transit leg of a Trip.
message TransitLeg {
  string id = 1;               // Unique identifier for the leg
  bool realtime = 2;           // Indicates if the data is real-time
  ServiceJourney serviceJourney = 3; // Information about the service journey
  string serviceDate = 4;      // Date of the service in YYYY-MM-DD format
  repeated Situation situations = 5; // List of associated situations
  EstimatedCall fromEstimatedCall = 6; // Estimated call at the start
  EstimatedCall toEstimatedCall = 7;   // Estimated call at the end
  repeated EstimatedCall intermediateEstimatedCalls = 8; // Intermediate calls
  Line line = 9;               // Line information
  Authority authority = 10;    // Authority information (GTFS Agency, NeTEx Authority) - Prefer using the Operator information over Authority. Kept for backwards compatability only.
  enumerations.TransitMode mode = 11;       // Mode of transport
  bool staySeated = 12;          // Indicates if passengers are expected to stay seated for the next transfer, e.g. two trips that are ran by the same vehicle with a change of line at an intermediate stop, or a bus that changes its line number at an intermediate stop.
  Operator operator = 13;           // Operator information for the transit leg (NeTEx only)
}

// Represents a non-transit leg of a Trip.
message NonTransitLeg {        // Base leg details
  Place fromPlace = 1;         // Starting place
  Place toPlace = 2;          // Destination place
  enumerations.NonTransitMode mode = 12;       // Mode of transport
  repeated Step steps = 3;     // Optional source steps; not populated by the current default non-transit mapper.
  optional string tripWeatherJson = 4; // Reserved weather JSON; not populated by the current default planning pipeline.
  repeated string rentalNetworks = 5; // List of bike rental networks that are available for this leg, if it's a shared mobility leg
}

// Represents a flexible (on-demand) transit leg of a Trip.
message FlexibleLeg {
  string id = 1;               // Unique identifier for the leg
  FlexibleServiceJourney serviceJourney = 2; // Information about the service journey
  string serviceDate = 4;      // Date of the service in YYYY-MM-DD format
  Place fromPlace = 6;         // Start place (flex pickup area or point)
  Place toPlace = 7;           // End place (flex dropoff area or point)
  Line line = 8;               // Line information
  Authority authority = 9;     // Authority information
  enumerations.TransitMode mode = 10;      // Mode of transport
  BookingArrangement bookingArrangement = 11; // Booking arrangement details
  double distance = 12;        // Distance travelled during the flexible leg in meters
  bool arrivalTimeUncertain = 13; // Indicates if the arrival time is uncertain (due to on-demand nature)
  bool departureTimeUncertain = 14; // Indicates if the departure time is uncertain (due to on-demand nature)
  Operator operator = 15;           // Operator information for the transit leg (NeTEx only)
}

message FlexibleServiceJourney {
  string id = 1;               // Unique identifier for the service journey
  enumerations.TransitMode transportMode = 2;    // Mode of transport (probably always "BUS")
  optional bool wheelchairAccessible = 3; // Wheelchair accessibility info
  repeated Situation situations = 4; // Alerts attached to this service journey
}

// Represents a waiting leg inserted between public transport legs.
message WaitingLeg {
  string startTime = 1; // Start of waiting period (ISO 8601)
  string endTime = 2;   // End of waiting period (ISO 8601)
}

// Represents a service journey (e.g., bus or train trip details).
message ServiceJourney {
  string id = 1;               // Unique identifier for the service journey (NeTEx)
  enumerations.TransitMode transportMode = 2;    // Mode of transport (e.g., "RAIL", "TRAM")
  string publicCode = 3;       // Public-facing code (e.g., train or bus number)
  optional string transportSubmode = 4; // Transport submode
  optional enumerations.DirectionType directionType = 5;    // Direction type
  optional bool wheelchairAccessible = 6; // Wheelchair accessibility info
  optional bool bikesAllowed = 7;     // Bikes allowed info
  repeated Notice notices = 8; // Notices associated with the journey -- This is filled only from NeTEx sources!
  string privateCode = 9;     // Private code for the journey (BISON: JourneyNumber)
  repeated Situation situations = 10; // Source alerts scoped to this service journey, when supplied.
}

// Represents a notice that may be associated with a journey or leg.
message Notice {
  string text = 1; // Notice text
  optional string id = 2; // Unique identifier for the notice
  optional string publicCode = 3; // Public-facing code for the notice
}

// Represents a place with geographic coordinates.
message Place {
  string name = 1;             // @required Name of the place, e.g. "Amsterdam Centraal Station"
  double latitude = 2;         // @required Latitude in WGS84
  double longitude = 3;        // @required Longitude in WGS84

  optional Quay quay = 4;               // @optional - Only for (flexible) transit places
  optional BikeRentalStation bikeRentalStation = 5; // @optional - Only for bike rental stations on non-transit legs
  optional RentalVehicle rentalVehicle = 6; // @optional - Only for rental vehicles on non-transit legs
}

// Represents a public transport situation (e.g., disruption or alert).
message Situation {
  string id = 1;               // Unique identifier for the situation
  string description = 2;      // Backwards-compatible preferred description text
  repeated MultilingualString advice = 3;
  repeated MultilingualString summaries = 4;
  repeated MultilingualString descriptions = 5;
  repeated InfoLink infoLinks = 6;
  optional ValidityPeriod validityPeriod = 7;
  optional string reportType = 8;
  optional string severity = 9;
  optional string participant = 10;
  optional int32 priority = 11;
  optional string situationNumber = 12;
  optional int32 version = 13;
  optional string creationTime = 14; // ISO 8601
  optional string versionedAtTime = 15; // ISO 8601
  repeated SituationAffect affects = 16; // Exact entities and stop conditions affected by this situation
}

message SituationAffect {
  string type = 1; // Source affected-entity type
  optional string lineId = 2;
  optional string serviceJourneyId = 3;
  optional string stopPlaceId = 4;
  optional string quayId = 5;
  optional string operatingDay = 6;
  repeated string stopConditions = 7;
  optional string description = 8;
}

message MultilingualString {
  string value = 1;
  optional string language = 2; // ISO 639 language code when supplied by the source
}

message InfoLink {
  string uri = 1;
  optional string label = 2;
}

message ValidityPeriod {
  optional string startTime = 1; // ISO 8601
  optional string endTime = 2; // ISO 8601; absent for open-ended situations
}

// Represents an estimated call (stop information).
message EstimatedCall {
  Quay quay = 1;               // Quay information
  string aimedPlatform = 2;    // Aimed platform
  optional string expectedPlatform = 3; // Expected platform
  string aimedArrivalTime = 4; // Aimed arrival time in ISO 8601 format
  optional string expectedArrivalTime = 5; // Expected arrival time in ISO 8601 format
  optional string actualArrivalTime = 6; // Actual arrival time in ISO 8601 format
  string aimedDepartureTime = 7; // Aimed departure time in ISO 8601 format
  string expectedDepartureTime = 8; // Expected departure time in ISO 8601 format
  optional string actualDepartureTime = 9; // Actual departure time in ISO 8601 format
  optional uint32 stopPositionInPattern = 10; // Stop position in the pattern
  DestinationDisplay destinationDisplay = 11; // Destination display information
  bool cancelled = 12; // Stop is cancelled by schedule or realtime data; boarding and alighting are unavailable
}

// Represents destination display information.
message DestinationDisplay {
  string frontText = 1;        // Front display text
  repeated string via = 2;     // Via display texts
}

// Represents a line in public transport.
message Line {
  string id = 1;               // Unique identifier for the line
  string publicCode = 2;       // Public-facing code for the line
  string name = 3;             // Name of the line
  enumerations.TransitMode transportMode = 4;    // Mode of transport (e.g., "RAIL", "TRAM")
  optional string transportSubmode = 5; // Transport submode (E.g. U-Link, Q-Liner)
  Presentation presentation = 6; // Presentation details
  string privateCode = 7;     // Private code for the line (LinePlanningNumber)
  optional Branding branding = 8;       // Branding information for the line (NeTEx only, prefer using this over Operator/Authority information)
  repeated Situation situations = 9; // Alerts attached to this line
}

// Represents presentation details like colors for lines.
message Presentation {
  string colour = 1;           // Colour of the line
  string textColour = 2;       // Text colour of the line
}

message Branding {
  string id = 1;               // Unique identifier for the brand (NeTEx ID of the brand, e.g. "NL_NETEX:NL:CXX:Branding:BRENG") - This can be used to attach colors and logos.
  string name = 2;             // Name of the brand
  optional string shortName = 3;   // Short name of the brand, e.g. "NS" for "Nederlandse Spoorwegen" - Generally unused
  optional string url = 4;              // URL for the brand
  optional string description = 5;        // Description of the brand - Generally unused
  optional string image = 6;              // URL for an image/logo representing the brand
}

// Represents an authority in public transport. (Equivalent to a GTFS Agency or NeTEx Authority) - Prefer using the Operator information over Authority. Kept for backwards compatability only.
message Authority {
  string id = 1;               // Unique identifier for the authority. In NeTEx this is _NOT_ the operator. This can for example be: `NL_NETEX:DOVA:Authority:OVGD`
  string name = 2;             // Name of the authority. E.g. "OV Bureau Groningen-Drenthe"
  optional string url = 3;              // URL for the authority
  optional string timezone = 4;         // Timezone of the authority
  optional string phone = 5;            // Contact phone number
  optional string language = 6;         // Language of the authority
  optional string fareUrl = 7;          // URL for fares
  optional string dataOwnerCode = 8;   // Data owner code
}

// Represents an operator in public transport. (NeTEx only, for GTFS this contains the same information as Authority). For brand-information, use "Branding" on the "Line" message.
message Operator {
  string id = 1;               // NeTEx ID of the operator. E.g. "NL_NETEX:NL:CXX:Operator:CTS"
  string name = 2;             // Name of the operator. E.g. "Connexxion Taxi Srv"
  optional string phone = 3;            // Contact phone number
  optional string dataOwnerCode = 4;   // Data owner code E.g. "CXX".
}

// Represents a series of points defining a route.
message PointsOnLink {
  string points = 1;           // Encoded polyline points
  int32 length = 2;            // Length of the polyline
}

// Represents a step in a non-transit leg.
message Step {
  string description = 1;      // Description of the step
  double distance = 2;         // Distance of the step in kilometers
  int32 duration = 3;          // Duration of the step in minutes
}

// Represents a quay or platform in public transport.
message Quay {
  string id = 1;               // Unique identifier
  string name = 2;             // Name of the quay
  double latitude = 3;         // Latitude in WGS84
  double longitude = 4;        // Longitude in WGS84
  string description = 5;      // Description of the quay
  string stopType = 6;         // Type of stop (e.g., 'regular')
  bool wheelchairAccessible = 7; // Non-optional source accessibility flag; default false cannot distinguish unknown by presence.

  repeated TariffZone tariffZones = 9; // Tariff zones of the quay
  string publicCode = 10;       // Public code of the quay (Platform)

  string quayCode = 11;        // Quay code (userStopCode KV1, stationCode IFF, in the future quayCode from CHB)

  string town = 12;             // Town or city where the quay is located, if not filled, you can assume it's part of the quay name. Use "includeTownInStopName" parameter to include the town in the quay name in the response for backwards compatibility.

  // Alerts attached to the parent stop place. Quay is the stop-level entity exposed by this API.
  repeated Situation situations = 13;

  reserved 8; // Depricated "flexibleArea" field
  reserved "flexibleArea"; // Depricated "flexibleArea" field
}

// Represents a tariff zone in public transport.
message TariffZone {
  string id = 1;               // Identifier for the tariff zone
  string name = 2;             // Name of the tariff zone
}

//Represents a bike rental station
message BikeRentalStation {
  string id = 1; // Unique identifier for the station, specified in GBFS
  string name = 2;
  uint32 bikesAvailable = 3;
  uint32 spacesAvailable = 4;
  bool realtimeOccupancyAvailable = 5; // Do we have real-time occupancy data?
  bool allowDropoff = 6;
  repeated string networks = 7;
}

// Represents a type of vehicle (e.g., bike, scooter)
message VehicleType {
  string name = 1;
  string formFactor = 2;
  string propulsionType = 3;
  int32 maxRangeMeters = 4;
  string vehicleTypeId = 5;

  double longitude = 6;
  double latitude = 7;
}

// Represents a rental vehicle (e.g., shared bike or scooter)
message RentalVehicle {
  string id = 1;
  string network = 2;
  double longitude = 3;
  double latitude = 4;
  VehicleType vehicleType = 5;
  optional double currentRangeMeters = 6;
}

/*
  Details on how to book an on-demand service, if applicable.
  May be absent even on an on-demand trip when the source supplies no booking details.
 */
message BookingArrangement {
  /*
    The phone number to book the on-demand service, in international format (e.g., +31612345678)
   */
  optional string phoneNumber = 1;

  /*
    The URL to book the on-demand service, if available
   */
  optional string bookingUrl = 2;

  /**
    The url for further information about the on-demand service, if available
   */
  optional string infoUrl = 5;

  /*
    How many days in advance maximum the booking can be made. If absent, no limit information is supplied by this response.
   */
  optional int32 earliestBookingDayInAdvance = 3;

  /*
    The date that the booking must be made latest, if applicable. If absent, no limit information is supplied by this response.
   */
  optional string latestBookingTime = 4; // Full ISO 8601 deadline with offset, calculated from departure minus minimum booking period.

  /**
    Note about booking, e.g. "Booking required", "Book at least 30 minutes in advance", etc.
   */
  optional string note = 6;
}

/** Represents pricing information for a trip */
message PricingInformation {
  int32 totalPrice = 1; // Total price of the trip - in cents
  string currency = 2;   // Currency code (e.g., "USD", "EUR")

  repeated LegPrice legPrice = 3; // Price breakdown per leg
  repeated PricingTransferInstruction transferInstruction = 11;

  reserved 4 to 10; // Reserved for future use (E.g., taxes, fees, discounts)
}

/** Represents pricing information for a specific leg of a trip */
message LegPrice {
  uint32 legIndex = 1; // Index of the leg in the trip
  int32 basePrice = 2; // Base price for the leg - in cents
  int32 priceWithoutDiscounts = 3; // Price without any discounts - in cents
  int32 finalPrice = 4; // Final price after discounts - in cents
  PriceStatus status = 5; // Status of the price calculation
  repeated AppliedDiscount discounts = 6; // Discounts applied to this leg

  reserved 7 to 12; // Reserved for future use (E.g., taxes, fees, discounts)
}

message PricingTransferInstruction {
  uint32 fromLegIndex = 1;
  uint32 toLegIndex = 2;
  Authority checkoutFrom = 3;
  Authority checkInTo = 4;
}

message AppliedDiscount {
  string type = 1; // Discount type identifier
  string description = 2; // Human-readable discount description
  int32 amount = 3; // Discount amount in cents
  optional double percentage = 4; // Optional discount percentage
}

enum PriceStatus {
  CALCULATED = 0;
  UNKNOWN = 1;
}
