-- Create custom data types

CREATE TYPE ropidgtfs_transfer_type AS ENUM ('0', '1', '2', '3', '4', '5');

-- Create parent table for GTFS transfers with check constraints and indexes

CREATE TABLE ropidgtfs_transfers (
    from_stop_id varchar(255) NULL,
    to_stop_id varchar(255) NULL,
    from_trip_id varchar(255) NULL,
    to_trip_id varchar(255) NULL,
    transfer_type ropidgtfs_transfer_type NOT NULL,
    min_transfer_time int4 NULL,
    max_waiting_time int4 NULL,
    -- audit columns
    create_batch_id int8 NULL,
    created_at timestamptz NULL,
    created_by varchar(150) NULL,
    update_batch_id int8 NULL,
    updated_at timestamptz NULL,
    updated_by varchar(150) NULL,
    -- constraints
    CONSTRAINT ropidgtfs_transfers_unique_idx UNIQUE NULLS NOT DISTINCT (from_stop_id, to_stop_id, from_trip_id, to_trip_id),
    CONSTRAINT ropidgtfs_transfers_from_stop_id_nonempty CHECK (char_length(from_stop_id) > 0),
    CONSTRAINT ropidgtfs_transfers_to_stop_id_nonempty CHECK (char_length(to_stop_id) > 0),
    CONSTRAINT ropidgtfs_transfers_from_trip_id_nonempty CHECK (char_length(from_trip_id) > 0),
    CONSTRAINT ropidgtfs_transfers_to_trip_id_nonempty CHECK (char_length(to_trip_id) > 0),
    CONSTRAINT ropidgtfs_transfers_min_transfer_time_nonnegative CHECK (min_transfer_time >= 0),
    CONSTRAINT ropidgtfs_transfers_max_waiting_time_nonnegative CHECK (max_waiting_time >= 0),
    CONSTRAINT ropidgtfs_transfers_conditionally_required_columns CHECK (
        CASE WHEN transfer_type in ('1', '2', '3')
            THEN from_stop_id IS NOT NULL AND to_stop_id IS NOT NULL
            ELSE CASE WHEN transfer_type in ('4', '5')
                THEN from_trip_id IS NOT NULL AND to_trip_id IS NOT NULL
                ELSE TRUE
            END
        END
    )
);

CREATE INDEX ropidgtfs_transfers_from_stop_id_to_stop_id_idx ON ropidgtfs_transfers USING btree (from_stop_id, to_stop_id);
CREATE INDEX ropidgtfs_transfers_from_trip_id_to_trip_id_idx ON ropidgtfs_transfers USING btree (from_trip_id, to_trip_id);
CREATE INDEX ropidgtfs_transfers_transfer_type_idx ON ropidgtfs_transfers USING btree (transfer_type);

COMMENT ON TABLE ropidgtfs_transfers IS '
GTFS information about guaranteed transfers (from the file `transfers.txt`).

See also GTFS Schedule Reference for `transfers.txt` at <https://gtfs.org/documentation/schedule/reference/#transferstxt>.
';

COMMENT ON COLUMN ropidgtfs_transfers.max_waiting_time IS '
Maximum waiting time in seconds.

This is a custom extension to GTFS transfers to allow specifying a maximum waiting time for a transfer.
For instance a bus waits for a train, but at most 20 minutes. If the train is delayed more than 20 minutes,
the bus leaves and the passengers need to wait for the next bus.

If empty (`NULL`), the vehicle waits forever or the waiting time could not be specified.

See also feature request to add the column to GTFS at <https://github.com/google/transit/issues/372>.
';

-- Create child (actual) table for GTFS transfers with check constraints and indexes

CREATE TABLE ropidgtfs_transfers_actual (
    LIKE ropidgtfs_transfers INCLUDING ALL
) INHERITS (ropidgtfs_transfers);

-- Update procedures for working with tmp tables

CREATE OR REPLACE PROCEDURE ropidgtfs_preparetmptables()
 LANGUAGE plpgsql
 SET search_path from CURRENT
AS $procedure$
	begin
		CALL ropidgtfs_cleanTmpTables();
		CALL ropidgtfs_cleanOldTables();
		CALL ropidgtfs_prepareTmpTable('ropidgtfs_agency');
		CALL ropidgtfs_prepareTmpTable('ropidgtfs_calendar');
		CALL ropidgtfs_prepareTmpTable('ropidgtfs_calendar_dates');
		CALL ropidgtfs_prepareTmpTable('ropidgtfs_shapes');
		CALL ropidgtfs_prepareTmpTable('ropidgtfs_stop_times');
		CALL ropidgtfs_prepareTmpTable('ropidgtfs_stops');
		CALL ropidgtfs_prepareTmpTable('ropidgtfs_routes');
		CALL ropidgtfs_prepareTmpTable('ropidgtfs_route_sub_agencies');
		CALL ropidgtfs_prepareTmpTable('ropidgtfs_transfers');
		CALL ropidgtfs_prepareTmpTable('ropidgtfs_trips');
		CALL ropidgtfs_prepareTmpTable('ropidgtfs_cis_stops');
		CALL ropidgtfs_prepareTmpTable('ropidgtfs_cis_stop_groups');
		CALL ropidgtfs_prepareTmpTable('ropidgtfs_run_numbers');
		CALL ropidgtfs_prepareTmpTable('ropidgtfs_ois');
		alter table ropidgtfs_stop_times_tmp drop computed_dwell_time_seconds;
		alter table ropidgtfs_stop_times_tmp add computed_dwell_time_seconds int2 NOT NULL GENERATED ALWAYS AS (calculate_dwell_time_seconds(arrival_time, departure_time)) stored;
        alter table ropidgtfs_stops_tmp drop column computed_cis_stop_id;
        alter table ropidgtfs_stops_tmp add column computed_cis_stop_id text generated always as (asw_node_id::text || '/' || asw_stop_id::text) stored;
	end
$procedure$
;

CREATE OR REPLACE PROCEDURE ropidgtfs_cleanoldtables()
 LANGUAGE plpgsql
 SET search_path from CURRENT
AS $procedure$
	begin
		drop table if exists "ropidgtfs_agency_old";
		drop table if exists "ropidgtfs_calendar_old";
		drop table if exists "ropidgtfs_calendar_dates_old";
		drop table if exists "ropidgtfs_shapes_old";
		drop table if exists "ropidgtfs_stop_times_old";
		drop table if exists "ropidgtfs_stops_old";
		drop table if exists "ropidgtfs_routes_old";
		drop table if exists "ropidgtfs_route_sub_agencies_old";
		drop table if exists "ropidgtfs_transfers_old";
		drop table if exists "ropidgtfs_trips_old";
		drop table if exists "ropidgtfs_cis_stops_old";
		drop table if exists "ropidgtfs_cis_stop_groups_old";
		drop table if exists "ropidgtfs_run_numbers_old";
		drop table if exists "ropidgtfs_ois_old";
		drop table if exists "ropidgtfs_precomputed_services_calendar_old";
		drop table if exists "ropidgtfs_precomputed_minmax_stop_sequences_old";
		drop table if exists "ropidgtfs_precomputed_trip_schedule_old";
	end
$procedure$
;

CREATE OR REPLACE PROCEDURE ropidgtfs_cleantmptables()
 LANGUAGE plpgsql
 SET search_path from CURRENT
AS $procedure$
	begin
		drop table if exists "ropidgtfs_agency_tmp";
		drop table if exists "ropidgtfs_calendar_tmp";
		drop table if exists "ropidgtfs_calendar_dates_tmp";
		drop table if exists "ropidgtfs_shapes_tmp";
		drop table if exists "ropidgtfs_stop_times_tmp";
		drop table if exists "ropidgtfs_stops_tmp";
		drop table if exists "ropidgtfs_routes_tmp";
		drop table if exists "ropidgtfs_route_sub_agencies_tmp";
		drop table if exists "ropidgtfs_transfers_tmp";
		drop table if exists "ropidgtfs_trips_tmp";
		drop table if exists "ropidgtfs_cis_stops_tmp";
		drop table if exists "ropidgtfs_cis_stop_groups_tmp";
		drop table if exists "ropidgtfs_run_numbers_tmp";
		drop table if exists "ropidgtfs_ois_tmp";
		drop table if exists "ropidgtfs_precomputed_services_calendar_tmp";
		drop table if exists "ropidgtfs_precomputed_minmax_stop_sequences_tmp";
		drop table if exists "ropidgtfs_precomputed_trip_schedule_tmp";
	end
$procedure$
;
