#!/usr/bin/env perl
use strict;
use warnings;
use 5.020;
use utf8;

our $VERSION = '0.04';

use Getopt::Long;
use List::Util qw(min);
use Travel::Status::DE::IRIS;
use Travel::Status::DE::DBWagenreihung;

my $developer_mode = 0;

binmode( STDOUT, ':encoding(utf-8)' );

sub show_help {
	my ($code) = @_;

	say "Usage: db-wagenreihung <station> <train number>";

	exit $code;
}

sub show_version {
	say "db-wagenreihung version ${VERSION}";

	exit 0;
}

GetOptions(
	'h|help'  => sub { show_help(0) },
	'devmode' => \$developer_mode,
	'version' => sub { show_version() },
) or show_help(1);

if ( @ARGV != 2 ) {
	show_help(1);
}

my ( $station, $train_number ) = @ARGV;

my $col_first  = "\e[38;5;11m";
my $col_mixed  = "\e[38;5;208m";
my $col_second = "\e[0m";          #"\e[38;5;9m";
my $col_reset  = "\e[0m";

my $res = Travel::Status::DE::IRIS->new(
	developer_mode => $developer_mode,
	station        => $station,
	with_related   => 1
);

if ( $res->errstr ) {
	say STDERR $res->errstr;
	exit 1;
}

my @trains = grep { $_->train_no eq $train_number } $res->results;

if ( @trains != 1 ) {
	say STDERR "Unable to find train in reported departures";
	exit 1;
}

my $wr = Travel::Status::DE::DBWagenreihung->new(
	departure      => $trains[0]->sched_departure || $trains[0]->sched_arrival,
	developer_mode => $developer_mode,
	train_number   => $train_number,
);

printf(
	"%s: %s → %s  (%s)\n%s Gleis %s\n\n",
	join( ' / ', map { $wr->train_type . ' ' . $_ } $wr->train_numbers ),
	join( ' / ', $wr->origins ),
	join(
		' / ',
		map {
			sprintf( '%s (%s)', $_->{name}, join( q{}, @{ $_->{sections} } ) )
		} $wr->destinations
	),
	$wr->train_subtype // 'IC?',
	$wr->station_name,
	$wr->platform
);

for my $section ( $wr->sections ) {
	my $section_length = $section->length_percent;
	my $spacing_left   = int( ( $section_length - 2 ) / 2 ) - 1;
	my $spacing_right  = int( ( $section_length - 2 ) / 2 );

	if ( $section_length % 2 ) {
		$spacing_left++;
	}

	printf( "▏%s%s%s▕",
		' ' x $spacing_left,
		$section->name,
		' ' x $spacing_right );
}
print "\n";

my @start_percentages = map { $_->{position}{start_percent} } $wr->wagons;
print ' ' x ( ( min @start_percentages ) - 1 );
print $wr->direction == 100 ? '>' : '<';

for my $wagon ( $wr->wagons ) {
	my $wagon_length
	  = $wagon->{position}->{end_percent} - $wagon->{position}->{start_percent};
	my $spacing_left  = int( $wagon_length / 2 ) - 2;
	my $spacing_right = int( $wagon_length / 2 ) - 1;

	if ( $wagon_length % 2 ) {
		$spacing_left++;
	}

	my $wagon_desc = $wagon->number || '?';

	if ( $wagon->is_locomotive or $wagon->is_powercar ) {
		$wagon_desc = ' ■ ';
	}

	my $class_color = '';
	if ( $wagon->class_type == 1 ) {
		$class_color = $col_first;
	}
	elsif ( $wagon->class_type == 2 ) {
		$class_color = $col_second;
	}
	elsif ( $wagon->class_type == 12 ) {
		$class_color = $col_mixed;
	}

	printf( "%s%s%3s%s%s",
		' ' x $spacing_left, $class_color, $wagon_desc,
		$col_reset,          ' ' x $spacing_right );
}
print $wr->direction == 100 ? '>' : '<';
print "\n\n";

for my $wagon ( $wr->wagons ) {
	printf(
		"%3s: %3s %10s  %s\n",
		$wagon->number || '?',
		$wagon->model  || '???',
		$wagon->type, join( q{  }, $wagon->attributes )
	);
}

__END__

=head1 NAME

db-wagenreihung - Interface to Deutsche Bahn Wagon Order API

=head1 SYNOPSIS

B<db-wagenreihung> I<station> I<train-number>

=head1 VERSION

version 0.04

This is beta software: API and output format may change without notice.

=head1 DESCRIPTION

db-wagenreihung shows the wagon order of train I<train-number> at station
I<station> (must be a name or DS100 code) as reported by the Deutsche Bahn
Wagon Order API. As of April 2020, long-distance IC/EC/ICFE trains are widely
supported, and some regions (e.g. Stuttgart/Karlsruhe) also provide wagon
orders for select regional trains. Data accuracy varies, but seems to be
improving over time.

It is not possible to request the wagon order at a train's terminus station.
This is a known limitation.

The departure of I<train-number> must be in the time range between now and
two hours in the future.

=head1 EXAMPLES

=over

=item db-wagenreihung 'Essen Hbf' 723

Show wagon order of ICE 723 at Essen Hbf

=item db-wagenreihung TS 3259

Show wagon order of IRE 3259 at Stuttgart Hbf

=back

=head1 DEPENDENCIES

=over

=item * JSON(3pm)

=item * LWP::UserAgent(3pm)

=item * Travel::Status::DE::IRIS(3pm)

=back

=head1 AUTHOR

Copyright (C) 2018-2020 by Daniel Friesel E<lt>derf@finalrewind.orgE<gt>

=head1 LICENSE

This program is licensed under the same terms as Perl itself.
