/* eslint-disable @typescript-eslint/no-redundant-type-constituents */
import type { Feature, Point } from 'geojson';

import type { components } from './realtimerest.d.ts';

export { operations as RealtimeRestOperations } from './realtimerest.d.ts';

export declare type RealtimeChannelModeSuffix = '_schematic' | '';

export declare type RealtimeMode = 'raw' | 'schematic' | 'topographic';

export type RealtimeTrainsByRouteIdentifierResult =
  components['schemas']['TrainsByRouteIdentifierResult'];

export type RealtimeTrajectoryCollection =
  components['schemas']['TrajectoryCollection'];

export type RealtimeRouteIdentifierMatch =
  components['schemas']['RouteIdentifierMatch'];

/**
 * @type RealtimeBbox
 */
export type RealtimeBbox = (number | string)[];

export type RealtimeBuffer = [number, number];

export interface RealtimeBufferResponse {
  client_reference: '';
  content: RealtimeTrajectoryResponse[];
  source: 'buffer';
  timestamp: number;
}

export type RealtimeChannelName =
  | 'buffer'
  | 'extra_geoms'
  | 'healthcheck'
  | 'line'
  | 'websocket'
  | `deleted_vehicles${RealtimeChannelModeSuffix}`
  | `full_trajectory${RealtimeChannelModeSuffix}_${RealtimeTenant}_${RealtimeTrainId}`
  | `stopsequence_${RealtimeTenant}_${RealtimeTrainId}`
  | `timetable_${RealtimeStationId}`
  | `trajectory${RealtimeChannelModeSuffix}`;

export interface RealtimeDeletedVehiclesResponse {
  client_reference: null;
  content: string;
  source: `deleted_vehicles${RealtimeChannelModeSuffix}`;
  timestamp: number;
}

export interface RealtimeDeparture {
  aimedArrivalTime?: number;
  aimedDepartureTime?: number;
  arrivalDelay?: number;
  arrivalTime?: number;
  at_station_ds100?: string; // TODO Verify it still exists
  at_stoppoint: string;
  call_id: number;
  changes: unknown[];
  created_at: number;
  departureDelay?: number;
  departureTime?: number;
  formation?: unknown;
  fzo_estimated_time: number;
  has_fzo: boolean;
  has_realtime_journey: boolean;
  journey_start_time?: number;
  line: RealtimeLine;
  min_arrival_time?: number;
  new_to?: boolean; // TODO Verify it still exists
  next_stoppoints: string[];
  no_stop_between?: boolean; // TODO Verify it still exists
  no_stop_till?: unknown; // TODO Verify it still exists
  operator_provides_fzo: boolean;
  platform?: string;
  ris_aimed_time?: number;
  ris_estimated_time?: number;
  state: RealtimeStopState; /// (BOARDING|STOP_CANCELLED|JOURNEY_CANCELLED|HIDDEN)/
  tenant: RealtimeTenant;
  time?: number;
  timediff?: number; // TODO Verify it still exists
  timestamp?: number; // TODO Verify it still exists
  to: string[];
  train_id: RealtimeTrainId;
  train_number?: number;
  train_type?: number;
  updated_at: number;
  vehicle_mode?: string;
}

export interface RealtimeDepartureExtended extends RealtimeDeparture {
  cancelled?: boolean; // value generated by RealtimeAPI class
}

export type RealtimeElevatorState = 'ALL_OPERABLE' | string;

export interface RealtimeExtraGeom extends Feature {
  properties: RealtimeExtraGeomProperties;
}

export interface RealtimeExtraGeomDeleted {
  properties: RealtimeExtraGeomProperties;
  type: 'Deleted';
}

export interface RealtimeExtraGeomProperties {
  ref: number | string;
}

export type RealtimeExtraGeoms = Record<string, Feature[]>;

export interface RealtimeExtraGeomsResponse {
  client_reference: null;
  content: RealtimeExtraGeom | RealtimeExtraGeomDeleted;
  source: `extra_geoms`;
  timestamp: number;
}
export type RealtimeFeedCollection = components['schemas']['FeedCollection'];
export type RealtimeFeed = components['schemas']['Feed'];

export type RealtimeFullTrajectoryCollection =
  components['schemas']['FullTrajectoryCollection'];

export type RealtimeFullTrajectory = components['schemas']['FullTrajectory'];

export type RealtimeFullTrajectoryCollectionProperties =
  components['schemas']['FullTrajectoryCollectionProperties'];

export type RealtimeFullTrajectoryProperties =
  components['schemas']['FullTrajectoryProperties'];

export interface RealtimeHealth {
  heathly: boolean;
  service: RealtimeService;
  tenant: null | string;
}

export interface RealtimeHealthCheckResponse {
  client_reference: null;
  content: RealtimeHealth;
  source: 'healthcheck';
  timestamp: number;
}

export type RealtimeLine = components['schemas']['Line'];

export type RealtimeMot =
  | 'bus'
  | 'cablecar'
  | 'coach'
  | 'ferry'
  | 'funicular'
  | 'gondola'
  | 'rail'
  | 'subway'
  | 'tram';

export interface RealtimeNews {
  incident_program: boolean;
  messages: RealtimeNewsMessage[];
}

export interface RealtimeNewsMessage {
  content: string;
  lines: RealtimeLine[];
  title: string;
  updated: string; // TODO: ISO string
}

export interface RealtimeNewsTickerResponse {
  client_reference: null;
  content: RealtimeNews;
  source: `${RealtimeTenant}_newsticker`;
  timestamp: number;
}

export type RealtimeService =
  | 'redis_websocket_api'
  | 'tralis_fzo'
  | 'tralis_geofox'
  | 'tralis_newsticker'
  | 'tralis_stations'
  | 'tralis_vdv'
  | 'tralis_worker'
  | string;

export interface RealtimeStation extends Feature {
  geometry: Point;
  properties: RealtimeStationproperties;
}

export type RealtimeStationId = number;

export interface RealtimeStationproperties extends Feature {
  elevatorOutOfOrder: boolean;
  elevators: object;
  elevatorState: RealtimeElevatorState;
  hasAccessibility: boolean;
  hasAirport: boolean;
  hasElevator: boolean;
  hasZOB: boolean;
  name: string;
  networkLines: RealtimeLine[];
  tenant: RealtimeTenant;
  transfers: RealtimeTransfer[];
  uic: RealtimeStationId;
}

export interface RealtimeStationResponse {
  client_reference: null;
  content: RealtimeNews;
  source: `station_${RealtimeStationId}`;
  timestamp: number;
}

export interface RealtimeStop {
  aimedArrivalTime: number;
  aimedDepartureTime: number;
  arrivalDelay?: number;
  arrivalTime: number;
  cancelled: boolean;
  coordinate: number[];
  departureDelay: number;
  departureTime: number;
  formation_id?: unknown;
  noDropOff?: boolean;
  noPickUp?: boolean;
  platform?: unknown;
  state?: RealtimeStopState;
  stationId?: RealtimeStationId;
  stationName: string;
  stopUID: string;
}

export type RealtimeStopSequence = {
  vehicleType: number; // TODO: Verify this property exists
} & components['schemas']['StopSequence'];

export interface RealtimeStopSequenceResponse {
  client_reference: '';
  content: RealtimeStopSequence[];
  source: `stopsequence_${RealtimeTenant}_${RealtimeTrainId}`;
  timestamp: number;
}

export type RealtimeStopState =
  | 'BOARDING'
  | 'HIDDEN'
  | 'JOURNEY_CANCELLED'
  | 'LEAVING'
  | 'STOP_CANCELLED'
  | string;

export type RealtimeTenant = '' | 'sbb' | 'sbh' | 'sbm' | string;

export interface RealtimeTimetableResponse {
  client_reference: null;
  content: RealtimeDeparture;
  source: `timetable_${RealtimeStationId}`;
  timestamp: number;
}

export type RealtimeTrainId = string;

export type RealtimeTrajectory = {
  properties: RealtimeTrajectoryProperties;
} & components['schemas']['TrackerTrajectory'];

export type RealtimeTrajectoryProperties = {
  coordinate?: [number, number]; // Added by RealtimeEnging after first rendering on a map
  delay: null | number; // Override REST api defs:
  event?: string;
  event_delay?: number;
  line: RealtimeLine; // TOOD verfy why this does not appears in the REST api schema
  name?: string; // deprecated, name is an old property, use line.name instead.
  operator?: string; // deprecated, operator is an old property, use tenant instead.
  original_line?: RealtimeLine;
  original_rake?: string;
  original_train_number?: number;
  position_correction?: number;
  rake?: string;
  raw_coordinates?: [number, number];
  raw_time?: string;
  ride_state?: string;
  rotation?: number; // Added by realtime engine  after first rendering on a map
  train_number?: number;

  transmitting_vehicle?: string;
} & components['schemas']['TrackerTrajectoryProperties'];

export interface RealtimeTrajectoryResponse {
  client_reference: '';
  content: RealtimeTrajectory;
  source: `trajectory${RealtimeChannelModeSuffix}`;
  timestamp: number;
}

export type RealtimeTrajectoryState =
  | 'BOARDING'
  | 'HIDDEN'
  | 'JOURNEY_CANCELLED'
  | 'STOP_CANCELLED';

export interface RealtimeTransfer {
  lines: string[];
  mot: RealtimeMot;
}
