#!/usr/bin/perl

# this is a shell command the user can use to deal with his homebanking

use FindBin;
use Data::Dumper;
use lib "$FindBin::Bin/lib"; # load modules from "lib" subdir relative to this script
use Finance::Bank::IE::PermanentTSB;
use Getopt::Long;
use Date::Calc qw(check_date);
use Switch;

sub usage {
  use Pod::Usage;
  pod2usage(-verbose =>1);
}

# main program
sub main {

    my $cf = {};

    # parse and validate options
    parse_options($cf);
    validate_options($cf);
    
    # read config file
    ($cf->{open24_num}, $cf->{pass}, $cf->{pan}) = 
        parse_configfile($cf->{cfgfile});

    print STDERR Dumper($cf) if($cf->{debug});

    # execute options
    if($cf->{balance}) {
        balance($cf);
    }
    if($cf->{statement}) {
        statement($cf);
    }

    # exit
    exit 0;

}

main;

# parse config file to retrieve acc_no, password and pan
sub parse_configfile {
    my $cfgfile = shift;
    open(FILE, $cfgfile) or 
        die "Cannot open config file $cfgfile. Error was: \"$!\"\n";
    while(<FILE>) {
        if(not /^\s{0,}#/ or not /^\s{0,}/) {
            my ($key, $val) = split '=';
            $val =~ s/^\s+//;
            $val =~ s/\s+$//;
            $user = $val if($key eq 'open24_number');
            $pass = $val if($key eq 'password');
            $pan = $val if($key eq 'pan');
        }
    }
    close FILE;

    # die if some of the arguments are undef
    foreach $i ($user, $pass, $pan) {
        if(not defined $i) {
            die ("invalid configuration file!");
        }
    }


    return ($user, $pass, $pan);
}

sub parse_options {

    my $cf = shift;

    # set some defaults

    # default config file is in ~/.ptsbrc
    $cf->{cfgfile} = $ENV{HOME}."/.ptsbrc";
    $cf->{no_balance} = 0;

    # =o -> Extended integer, Perl style. This can be either an optional
    # leading plus or minus sign, followed by a sequence of digits, or
    # an octal string (a zero, optionally followed by '0', '1', .. '7'),
    # or a hexadecimal string (0x followed by '0' .. '9', 'a' .. 'f',
    # case insensitive), or a binary string (0b followed by a series of
    # '0' and '1').
    #
    # =s -> string
    # =i -> integer

    my $error;
    # be case sensitive!
    Getopt::Long::Configure ("bundling");
    # pase opts, put everything in the $cf hash_ref
    Getopt::Long::GetOptions(
        "file|f=s" => \$cf->{'cfgfile'},
        "help|h" => \$cf->{'help'},
        "debug|D" => \$cf->{'debug'},
        "balance|b" => \$cf->{'balance'},
        "statement|s" => \$cf->{'statement'},
        "statement-type|T=s" => \$cf->{'statement_type'},
        "from-date|f=s" => \$cf->{'fromdate'},
        "to-date|t=s" => \$cf->{'todate'},
        "account-type|a=s" => \$cf->{'acc_type'},
        "account-num|n=s" => \$cf->{'acc_no'},
        "no-balance|N" => \$cf->{'no_balance'},
        "regexp|r=s" => \$cf->{'regexp'},
        "version|v" => \$cf->{'version'},
    ) or $error = 1;

    usage if($error or $cf->{'help'});

}

sub validate_options {

    my $cf = shift;


    # balance and statement cannot stay together
    if($cf->{balance} and $cf->{statement}) {
        print "You can not select -s and -b together!\n";
        print "You can only select one operation at a time!\n";
        exit -1;
    }

    if(defined $cf->{acc_type}) {
        # acc_type must be 'c' or 'v'
        switch ($cf->{acc_type}) {
            case "c" { $cf->{acc_type} = SWITCH_ACCOUNT; }
            case "v" { $cf->{acc_type} = VISA_ACCOUNT; }
            else     {
                print("Account type invalid\n");
                exit -1;
            }
        }
    }
    
    if(defined $cf->{statement_type}) {
        # acc_type must be 'c' or 'v'
        switch ($cf->{statement_type}) {
            case /WITHDRAWAL/is { $cf->{statement_type} = WITHDRAWAL; }
            case /DEPOSIT/is { $cf->{statement_type} = DEPOSIT; }
            case /ALL/is { $cf->{statement_type} = ALL; }
            else     {
                print("Statement type invalid\n");
                exit -1;
            }
        }
    }

    if(defined $cf->{version}) {
        print Finance::Bank::IE::PermanentTSB->VERSION, "\n";
        exit 0;
    }

    # all the other check are made by Finance::Bank::IE::PermanentTSB
}

sub balance {
    
    my $cf = shift;

    my %config = (
        "open24numba" => $cf->{open24_num},
        "password" => $cf->{pass},
        "pan" => $cf->{pan},
        "debug" => $cf->{debug},
    );

    my @balance = Finance::Bank::IE::PermanentTSB->check_balance(
        \%config, 
        $cf->{acc_type}, 
        $cf->{acc_no}, 
        $cf->{fromdate},
        $cf->{todate});

    print STDERR Dumper(@balance) if($cf->{debug});

    my $colname = "Account name";
    my $coldigit = "Acc. #";
    my $colbal = "Balance";
    my $colavail = "Available";
    for(0...58) { 
        print("-"); 
    }
    print "\n";

    printf("| %18s | %6s | %11s | %11s |", $colname, $coldigit, $colbal,
        $colavail);
    print "\n";
    for(0...58) { 
        print("-"); 
    }
    print "\n";

    foreach my $row (@balance) {
        printf("| %18s | %6s | %11s | %11s |\n",
            $row->{accname},
            $row->{accno},
            $row->{accbal},
            $row->{availbal});
    }
    
    for(0...58) { 
        print("-"); 
    }
    print "\n";


}

sub statement {

    my $cf = shift;
    my $counter_deposit;
    my $counter_withdrawal;

    my %config = (
        "open24numba" => $cf->{open24_num},
        "password" => $cf->{pass},
        "pan" => $cf->{pan},
        "debug" => $cf->{debug},
    );

    my @statement = Finance::Bank::IE::PermanentTSB->account_statement(
        \%config,
        $cf->{acc_type},
        $cf->{acc_no},
        $cf->{fromdate},
        $cf->{todate},
        $cf->{statement_type},
    );

    print STDERR Dumper(@statement) if($cf->{debug});

    if ($cf->{no_balance}) {
        for(0...54) { 
            print("-"); 
        }
    } else {
        for(0...68) { 
            print("-"); 
        }
    }
    print "\n";
    my $coldate = "Date"; 
    my $coldesc = "Description";
    my $colam   = "Amount";
    my $colbal  = "Balance";
    printf("| %10s | %24s | %11s |", $coldate, $coldesc, $colam);
    printf(" %11s |", $colbal) if(not $cf->{no_balance});
    print "\n";
    if ($cf->{no_balance}) {
        for(0...54) { 
            print("-"); 
        }
    } else {
        for(0...68) { 
            print("-"); 
        }
    }
    print "\n";

    my $print = 1;
    foreach my $row (@statement) {
        my $regex = $cf->{regexp};
        if($row->{description} =~ /$regex/is) {
            $print = 1;
        } else {
            $print = 0;
        }
        if($print) {
            printf("| %s | %24s | %11s ",
                $row->{date},
                $row->{description},
                $row->{euro_amount},
            );
            if(not $cf->{no_balance}) {
                printf "| %11s ", $row->{balance};
            }
            print "|\n";
            if($row->{euro_amount}<0) {
                $counter_withdrawal += $row->{euro_amount};
            } else {
                $counter_deposit += $row->{euro_amount};
            }
        }

    }
    if ($cf->{no_balance}) {
        for(0...54) { 
            print("-"); 
        }
    } else {
        for(0...68) { 
            print("-"); 
        }
    }
    print "\n";


    print "\n=== Totals ===\n";
    if($cf->{statement_type} == ALL or $cf->{statement_type} == DEPOSIT) {
        print "Total deposit: $counter_deposit\n";
    }
    if($cf->{statement_type} == ALL or $cf->{statement_type} ==
        WITHDRAWAL) {
        print "Total withdrawal: $counter_withdrawal\n";
    }
    if($cf->{statement_type} == ALL) {
        printf("Profit: %f\n", $counter_deposit+$counter_withdrawal);
    }

}

__END__

=head1 NAME

ptsb - Interact with you Permanent TSB homebanking!

=head1 SYNOPSIS

ptsb [options] 

=head2 Print accounts balance:

=over 2

ptsb [ -F F</path/of/conf/file> ] -b

=back

=head2 Print account statement:

=over 2

ptsb [ -F F</path/of/conf/file> ] -s -a c -n <4digits>
       -f yyyy/mm/dd  -t yyyy/mm/dd

=back

=head1 OPTIONS

=over 8

=item B<-h | --help>

this help usage message!

=item B<-D | --debug>

Enable debug. This will be more verbose and will leave html
on the current working directory.

=item B<-F F</path/to/config/file> | --file F</path/to/config/file>>      

filename configuration file path (default: F<~/.ptsbrc>).
Please refer to manual page to see how this file is built.

=item B<-b | --balance>
                     
print account balance

=item B<-s | --statement>

print account statement

=item B<-T type | --transation-type type>

Type of transaction to look on the statement.
Type can be: ALL, WITHDRAWAL, DEPOSIT

=item B<-f | --from--date yyyy/mm/dd>

from date

=item B<-t | --to-date yyyy/mm/dd>

to date

=item B<-a [c | v] | --account-type [c | v]>

account type: can be 'c' (current account) or 'v' for (visa card)

=item B<-n digits | --account-num digits>

4 digits representing the last 4 digits of the account number or visa
card number.

=item B<-N | --no-balance>

Do not print balance when printing statement.

=item B<-r | --regexp>

When printing statement grep using the regexp provided

=item B<-v | --version>

Print version

=back

=head1 CONFIGURATION FILE

Configuration file default location is F<~/.ptsbrc> and it looks like this:

    -------8< -- ~/.ptsbrc -->8----------

    open24_number=your_open24_number

    password=your_internet_password

    pan=your_personal_access_number

    -------8< --------------->8----------

However you can put wherever you want. Just remember to use then the
option -F F</path/to/your/location>.

Lines beginning with # will be interpreted as comment.

=head1 SEE ALSO

=item * B<Official CPAN page for Finance::Bank::IE::PermanentTSB>

L<http://search.cpan.org/~pallotron/Finance-Bank-IE-PermanentTSB/lib/Finance/Bank/IE/PermanentTSB.pm>

=item * B<Author homepage>

L<http://www.pallotron.net>

=item * B<Author Blog (italian)>

L<http://www.vitadiunsysadmin.net>

=item * B<Author homepage on CPAN>

L<http://search.cpan.org/~pallotron/>

=head1 AUTHOR

Angelo "pallotron" Failla - <pallotron@freaknet.org>

=head1 BUGS

Please report bugs to the author, no bug tracking system is set up yet.

=head1 COPYRIGHT AND LICENSE

Copyright (C) 2009 by Angelo "pallotron" Failla

This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.8 or,
at your option, any later version of Perl 5 you may have available.
