#!/usr/bin/perl -w
use strict;
use warnings;
use Finance::FITF;
use Getopt::Long;
use DateTime;
use YAML::Syck;
use DateTime::Format::Strptime;
use DateTime::Format::ISO8601;

my ($show_bar, $show_tick, $start,  $header, $all);
my $n = 10;
my $format = 'OHLCVD';
my $date_format = '%F %T';
my %format_map = ( O => 'open',
                   H => 'high',
                   L => 'low',
                   C => 'close',
                   V => 'volume',
                   T => 'ticks',
                   D => 'date',
               );

GetOptions("header"  => \$header,
           "bar"     => \$show_bar,
           "tick"    => \$show_tick,
           "all"     => \$all,
           "format"  => \$format,
           "date_format" => \$date_format,
           "start=s" => \$start,
           "length=s"=> \$n);

my $data = Finance::FITF->new_from_file(shift || die "usage: $0 <file>".$/ );
my $h = $data->header;
my $strp = DateTime::Format::Strptime->new( time_zone => $h->{time_zone},
                                            pattern => $date_format);

my $strp_iso = DateTime::Format::Strptime->new( time_zone => $h->{time_zone},
                                                pattern => '%FT%T');

$header = 1 if !$show_bar && !$show_tick;

if ($header) {
    print "FITF version $h->{version}".$/;
    print "name: $h->{name}".$/;
    print "date: $h->{date} ($h->{time_zone})".$/;
    for (0..2) {
        last unless $h->{start}[$_];
        print " Session ".($_+1).": "
            .DateTime->from_epoch(time_zone => $h->{time_zone},
                                  epoch => $h->{start}[$_])
            .' ~ '.
                DateTime->from_epoch(time_zone => $h->{time_zone},
                                     epoch => $h->{end}[$_]).$/
    }
    print "bar type: ".($h->{bar_seconds})." secs".$/;
    print "bars: ".$data->nbars.$/;
    print "ticks: ".$h->{records}.$/;
}

my $start_at = $h->{start}[0];

if ($start) {
    $start_at = ($strp->parse_datetime($start) ||
                     $strp_iso->parse_datetime($start)
                 )->epoch;
}

if ($all) {
    $n = $data->nbars - $data->bar_idx($start_at)-1;
}

if ($show_tick && ($h->{format} & FITF_TICK_FMT) == FITF_TICK_NONE ) {
    print "no ticks in file found".$/;
    undef $show_tick;
}

for (1..$n) {
    my $ts = $start_at + $h->{bar_seconds} * $_;
    my $bar = $data->bar_at($ts);
    if ($show_bar) {
        my @res;
        for (split //, $format) {
            my $field = $format_map{$_};
            push @res, $field eq 'date' ? $strp->format_datetime(
                DateTime->from_epoch(epoch => $ts,
                                     time_zone => $h->{time_zone}))
                : $bar->{$field};
        }
        print join("\t", @res).$/;
    }
    if ($show_tick) {
        $data->run_ticks($bar->{index}, $bar->{index} + $bar->{ticks} - 1,
                         sub {
                             print join("\t", @_).$/
                         });
    }
}

