The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
package WWW::IRail::API::Connections;
BEGIN {
  $WWW::IRail::API::Connections::AUTHORITY = 'cpan:ESSELENS';
}
BEGIN {
  $WWW::IRail::API::Connections::VERSION = '0.003';
}
use strict;

use Carp qw/croak/;
use Date::Format;
use DateTime::Format::Natural;
use HTTP::Request::Common;
use JSON::XS;
use XML::Simple;
use YAML qw/freeze/;


sub make_request {
    my %attr = ref $_[0] eq 'HASH' ? %{$_[0]} : @_;

    croak 'from is a required argument' unless defined $attr{from};
    croak 'to is a required argument' unless defined $attr{to};

    # reformat several different date input formats
    if ($attr{date} =~ m/^\d+$/ ) { $attr{date} = time2str( "%d%m%y", $attr{data} ) }
    elsif ($attr{date} =~ m/^\d{2}(\d{2})\W?(\d{2})\W?(\d{2})$/) {  $attr{data} = "$3$2$1" }

    # reformat time input formats
    if ($attr{date} =~ m/(\d{2})\W?(\d{2})/) { $attr{date} = "$1$2" }
    
    # if date contains words, try to parse it as natural language
    if ($attr{date} =~ m/\w/) {
        my $dateparser = new DateTime::Format::Natural(prefer_future => 1);
        my $dt = $dateparser->parse_datetime( $attr{date} );
        if($dateparser->success) { 
            $attr{'date'} = sprintf("%02d%02d%02d", $dt->day, $dt->month, substr($dt->year,2,2) );
            $attr{'time'} = sprintf("%02d%02d", $dt->hour, $dt->min);
        }
    }

    croak 'date could not be parsed' unless $attr{date} =~ m/^\d{6}$/ and int($attr{date}) != 0;

    my $url = 'http://dev.api.irail.be/connections/?'.
                join '&', map { $_.'='.$attr{$_} } 
                qw/from to date time/;

    my $req = new HTTP::Request(GET => $url);

    return $req;
}

sub parse_response {
    my ($http_response, $dataType) = @_;

    my $obj = XMLin($http_response->content,
        NoAttr => $dataType eq 'XML' ? 0 : 1,
        SuppressEmpty => '',
        NormaliseSpace => 2,
        ForceArray => [ 'connection','via' ],
        KeepRoot => $dataType =~ /XML/i ? 0 : 1,
        GroupTags => { connections => 'connection', vias => 'via' },
        KeyAttr => [],
    );

    for ($dataType) {
        /xml/i and return XMLout $obj, RootName=>'connections',KeepRoot => 0, GroupTags => { connections => 'connection', vias => 'via' };
        /json/i and return JSON::XS->new->ascii->pretty->allow_nonref->encode($obj);
        /yaml/i and return freeze $obj;
        /perl/i and return $obj;
    }

    return $obj; # default to perl

}

42;



=pod

=head1 VERSION

version 0.003

=head1 NAME

WWW::IRail::API::Connections - HTTP::Request builder and HTTP::Response parser for the IRail API (Train)Connection data

=head1 SYNOPSIS

    make_request( from => 'brussel noord', to => 'oostende' );

=head1 DESCRIPTION

This module builds a L<HTTP::Request> and has a parser for the
L<HTTP::Response>. It's up to you to transmit it over the wire. If don't want
to do that yourself, don't use this module directly and use L<WWW::IRail::API>
instead.

=head1 METHODS

=head2 make_request( I<key => 'val'> | I<{ key => 'val' }> )

C<from> and C<to> are the only arguments required, all time and date arguments default
to the current time and date on the iRail API side.

    make_request (
        from    => 'oostende',
        to      => 'brussel noord',
        date    => '2010-11-28' || '20101128' || 'tomorrow afternoon',   
        time    => '6:24' || 1290922133,        
    );

=head2 parse_response( I<$http_response>, I<dataType> )

parses the HTTP::Response you got back from the server, which if all went well contains XML.
That XML is then transformed into other data formats

=over 4

=item *

xml

=item *

XML

=item *

YAML

=item *

JSON

=item *

perl (default)

=back

=head3 example of output when dataType = 'xml'

=head1 METHODS

=begin xml

  <connections>
    <connection duration="4860">
      <arrival platform="3" station="OOSTENDE" time="1290932220" vehicle="BE.NMBS.IC529" />
      <departure platform="NA" station="BRUXELLES NORD" time="1290927360" vehicle="BE.NMBS.IC529" />
    </connection>
    <connection duration="5040">
      <arrival platform="7" station="OOSTENDE" time="1290934020" vehicle="BE.NMBS.IC829" />
      <departure platform="4" station="BRUXELLES NORD" time="1290928980" vehicle="BE.NMBS.IC1529" />
      <vias>
        <via station="BRUGGE" timeBetween="300" vehicle="BE.NMBS.IC1529">
          <arrival platform="5" time="1290932940" />
          <departure platform="7" time="1290933240" />
        </via>
      </vias>
    </connection>

    <!-- snip -->

  </connections>

=end xml

=head3 example of output when dataType = 'XML'

=begin xml

    <connections timestamp="1290926300" version="1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="connections.xsd">
      <connection id="0" duration="4860">
        <arrival delay="0" vehicle="BE.NMBS.IC529">
          <platform normal="1">3</platform>
          <station id="BE.NMBS.410" location="51.226518 2.927904" locationX="2.927904" locationY="51.226518">OOSTENDE</station>
          <time formatted="2010-11-28T08:17:00Z">1290932220</time>
        </arrival>
        <departure delay="0" vehicle="BE.NMBS.IC529">
          <platform normal="1">NA</platform>
          <station id="BE.NMBS.100" location="50.859658 4.360854" locationX="4.360854" locationY="50.859658">BRUXELLES NORD</station>
          <time formatted="2010-11-28T06:56:00Z">1290927360</time>
        </departure>
      </connection>
      <connection id="1" duration="5040">
        <arrival delay="0" vehicle="BE.NMBS.IC829">
          <platform normal="1">7</platform>
          <station id="BE.NMBS.410" location="51.226518 2.927904" locationX="2.927904" locationY="51.226518">OOSTENDE</station>
          <time formatted="2010-11-28T08:47:00Z">1290934020</time>
        </arrival>
        <departure delay="0" vehicle="BE.NMBS.IC1529">
          <platform normal="1">4</platform>
          <station id="BE.NMBS.100" location="50.859658 4.360854" locationX="4.360854" locationY="50.859658">BRUXELLES NORD</station>
          <time formatted="2010-11-28T07:23:00Z">1290928980</time>
        </departure>
        <vias name="via" number="1">
          <via id="0" timeBetween="300" vehicle="BE.NMBS.IC1529">
            <arrival platform="5">
              <time formatted="2010-11-28T08:29:00Z">1290932940</time>
            </arrival>
            <departure platform="7">
              <time formatted="2010-11-28T08:34:00Z">1290933240</time>
            </departure>
            <station id="BE.NMBS.85" location="51.197225 3.216728" locationX="3.216728" locationY="51.197225">BRUGGE</station>
          </via>
        </vias>
      </connection>

      <!-- snip -->
    </connections>

=end xml

=head3 example of output when dataType = 'JSON'

=begin json

  {
   "connections" : [
      {
         "duration" : "4860",
         "departure" : {
            "station" : "BRUXELLES NORD",
            "time" : "1290927360",
            "vehicle" : "BE.NMBS.IC529",
            "platform" : "NA"
         },
         "arrival" : {
            "station" : "OOSTENDE",
            "time" : "1290932220",
            "vehicle" : "BE.NMBS.IC529",
            "platform" : "3"
         }
      },
      {
         "duration" : "5040",
         "departure" : {
            "station" : "BRUXELLES NORD",
            "time" : "1290928980",
            "vehicle" : "BE.NMBS.IC1529",
            "platform" : "4"
         },
         "vias" : [
            {
               "station" : "BRUGGE",
               "timeBetween" : "300",
               "vehicle" : "BE.NMBS.IC1529",
               "departure" : {
                  "time" : "1290933240",
                  "platform" : "7"
               },
               "arrival" : {
                  "time" : "1290932940",
                  "platform" : "5"
               }
            }
         ],
         "arrival" : {
            "station" : "OOSTENDE",
            "time" : "1290934020",
            "vehicle" : "BE.NMBS.IC829",
            "platform" : "7"
         }
      },

      // ... snip ...
   ]
  }

=end json

=head3 example of output when dataType = 'YAML'

=for YAML  ---
 connections:
  - arrival:
      platform: 3
      station: OOSTENDE
      time: 1290932220
      vehicle: BE.NMBS.IC529
    departure:
      platform: NA
      station: BRUXELLES NORD
      time: 1290927360
      vehicle: BE.NMBS.IC529
    duration: 4860
  - arrival:
      platform: 7
      station: OOSTENDE
      time: 1290934020
      vehicle: BE.NMBS.IC829
    departure:
      platform: 4
      station: BRUXELLES NORD
      time: 1290928980
      vehicle: BE.NMBS.IC1529
    duration: 5040
    vias:
      - arrival:
          platform: 5
          time: 1290932940
        departure:
          platform: 7
          time: 1290933240
        station: BRUGGE
        timeBetween: 300
        vehicle: BE.NMBS.IC1529

=head3 example of output when dataType="perl" (default)

=for perl   $VAR1 = {
          'connections' => [
                           {
                             'duration' => '5040',
                             'departure' => {
                                            'station' => 'BRUXELLES NORD',
                                            'time' => '1290928980',
                                            'vehicle' => 'BE.NMBS.IC1529',
                                            'platform' => '4'
                                          },
                             'arrival' => {
                                          'station' => 'OOSTENDE',
                                          'time' => '1290934020',
                                          'vehicle' => 'BE.NMBS.IC829',
                                          'platform' => '7'
                                        }
                             'vias' => [
                                       {
                                         'station' => 'BRUGGE',
                                         'timeBetween' => '300',
                                         'vehicle' => 'BE.NMBS.IC1529',
                                         'departure' => {
                                                        'time' => '1290933240',
                                                        'platform' => '7'
                                                      },
                                         'arrival' => {
                                                      'time' => '1290932940',
                                                      'platform' => '5'
                                                    }
                                       }
                                     ],
                           },
            ]
    };

=head1 INSTALLATION

See perlmodinstall for information and options on installing Perl modules.

=head1 BUGS AND LIMITATIONS

No bugs have been reported.

Please report any bugs or feature requests through the web interface at
L<http://rt.cpan.org>.

=head1 AUTHOR

Tim Esselens <tim.esselens@gmail.com>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2010 by Tim Esselens.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=cut


__END__