#!/usr/bin/perl
#
# This software released under the terms of the GNU General Public License 2.0
#
# Copyright (C) 2003,2004 Brian M. Kelly locoburger@netscape.net http://www.locoburger.org/
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, version 2.0.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# brinance - simple UNIX command-line interface to Brinance Perl personal
#            finance planner tracker
#
#		tabstop = 3		(These two lines should line up)
#     tabstop = 3    (These two lines should line up)

use warnings;
use strict;

use lib "$ENV{HOME}/.brinance/lib";
use Brinance;

my $VERSION = "3.95";
my @arglist;

# We first pull apart all arguments and push them or their equivalent onto @arglist
foreach ( @ARGV )
{
	if ( /^--./ ) # GNU style option
	{
		if	 ( $_ eq "--help" ) {
			push (@arglist, "-h");
		}
		elsif ( $_ eq "--version" ) {
			push (@arglist, "-v");
		}
		elsif ( $_ eq "--credit" ) {
			push (@arglist, "-c");
		}
		elsif ( $_ eq "--debit" ) {
			push (@arglist, "-d");
		}
		elsif ( $_ eq "--balance" ) {
			push (@arglist, "-b");
		}
		elsif ( $_ eq "--datedcredit" ) {
			push (@arglist, "-C");
		}
		elsif ( $_ eq "--dateddebit" ) {
			push (@arglist, "-D");
		}
		elsif ( $_ eq "--datedbalance" ) {
			push (@arglist, "-B");
		}
		elsif ( $_ eq "--name" ) {
			push (@arglist, "-n");
		}
		elsif ( $_ eq "--create" ) {
			push (@arglist, "-r");
		}
		else {
			print STDERR "ERROR: Unrecognized GNU style option: '$_'\n";
			&usage (1);
		}
	}
	elsif ( /^-./ ) # regular group of options
	{
		# break the arg down into individual list elements
		my $argplace = 1;
		my @donelist = ();
		my $num = "";
		while ($argplace < (length $_))
		{
			my $curr_char = substr ($_, $argplace++, 1);
			if ($curr_char =~ /\d/)
			{
				$num .= $curr_char;
			}
			else
			{
				if ($num ne "")
				{
					push ( @donelist, $num );
					$num = "";
				}
				push ( @donelist, $curr_char );
			}
		}

		if ($num ne "")
		{
			push ( @donelist, $num );
		}

		foreach (@donelist)
		{
			push ( @arglist, "-$_" );
		}
	}
	else # not starting with -
	{
		push ( @arglist, $_ );
	}
}

# check if we need to convert old account# files to an accounts file
#  if so, suggest they run the included conversion script (don't want conv code in here..)
if ( !(-e "$Brinance::account_dir/accounts") and -e "$Brinance::account_dir/account0") {
	print "It looks like you've been running an older version of brinance.\n";
	print "You will need to convert your account files to the new format.\n";

	print "\nRun the 'conv/toV4' script that was included with this brinance package.\n";

	exit (1);
}

unless (@arglist)
{
	print STDERR "Need arguments.\nUse --help for more help\n";
	exit (1);
}

&Brinance::switch_acct (0); # sets us up to use account 0
&Brinance::update_future (); # sync with future transactions in account 0

# helper vars for processing args
my $skipnext = 0;
my $where = 0;
my $credit = 0; #Is the transaction a credit? Debit otherwise..

# Process the args
foreach (@arglist)
{
	if ( $skipnext ) { $skipnext--; $where++; next; }

	if (/^-(\d+)$/) {
		my $out = &Brinance::switch_acct ($1 + 0);

		if ( 1 == $out ) {
			print STDERR "WARNING: Created account 0 (this shouldn't happen here..)\n";
		}
		elsif ( 0 == $out ) {
			print "Now working with account $Brinance::current_acct\n";
		}
		elsif ( -1 == $out ) {
			print STDERR "ERROR: account $Brinance::current_acct doesn't exist.\nUse -r or --create\n";
			&usage (1);
		}
		else {
			print STDERR "ERROR: &Brinance::switch_acct undefined output. Check your data. Exitting..\n";
			exit (1);
		}

		&Brinance::update_future ();
	}
	elsif ( $_ eq "-v" ) {
		print "Brinance module version: " . &Brinance::version() . "\n";
		print "brinance CLI version: $VERSION\n";
		print "\n";
		print "Copyright (C) 2003,2004 Brian Kelly locoburger\@netscape.net\n";
		print "brinance comes with ABSOLUTELY NO WARRANTY\n";
		print "This is free software, and you are welcome to redistribute it\n";
		print "under certain conditions. See LICENSE for details.\n";
	}
	elsif ( $_ eq "-h" ) {
		&usage (0);
	}
	elsif ( $_ eq "-b" ) {
		print sprintf ("Balance: %.2f\n", &Brinance::balance ());
	}
	elsif ( $_ eq "-c" ) {
		$credit = 1;
		&CLItrans ();
	}
	elsif ( $_ eq "-d" ) {
		$credit = 0;
		&CLItrans ();
	}
	elsif ( $_ eq "-C" ) {
		$credit = 1;
		&CLIdatedtrans ();
	}
	elsif ( $_ eq "-D" ) {
		$credit = 0;
		&CLIdatedtrans ();
	}
	elsif ( $_ eq "-B" ) {
		if ( $arglist[$where+1] )
		{
			my $date;
			if ($arglist[$where+1] =~ /^\+(\d+)$/) {
				my (undef,$min,$hour,$mday,$mon,$year,undef,undef,undef) = localtime(time+($1*60*60*24));

				$year += 1900;
				$mon += 1;
				if ($mon < 10) {$mon = "0" . $mon;}
				if ($mday < 10) {$mday = "0" . $mday;}
				if ($hour < 10) {$hour = "0" . $hour;}
				if ($min < 10) {$min = "0" . $min;}
				$date = $year . $mon . $mday . $hour . $min;
			}
			elsif ($arglist[$where+1] =~ /^\d{12}$/) {
				$date = $arglist[$where+1];
			}
			else {
				print STDERR "ERROR: date not in 12-digit or +<days> format\n";
				&usage (1);
			}
			print sprintf ("account $Brinance::current_acct balance at $date: %.2f\n", &Brinance::balance ( $date ));
		}
		else {
			print STDERR "ERROR: dated balance requires an argument\n";
			&usage (1);
		}
		$skipnext = 1;
	}
	elsif ( $_ eq "-n" ) {
		if ( my $out = &Brinance::getName () )
		{
			print "account $Brinance::current_acct name: $out\n";
		}
		else
		{
			print "No name for account $Brinance::current_acct\n";
		}
	}
	elsif ( $_ eq "-r" ) {
		if ( $arglist[$where+2] && length($arglist[$where+1]) )
		{
			my $out = &Brinance::create ( $arglist[$where+2], $arglist[$where+1] );

			if ( 1 == $out )
			{
				# already exists
				print "account $arglist[$where+1] already exists\n";
				exit (0);
			}
			elsif ( 0 == $out )
			{
				# success
				print "account $arglist[$where+1] created successfully\n";
			}
			elsif ( -1 == $out )
			{
				# too few
				print "too few arguments to create()\n";
			}
			else
			{
				print STDERR "ERROR: undefined output from Brinance::getName(); Check your accounts file..\n";
				print "Exitting..\n";
				exit (1);
			}

			$skipnext = 2;
		}
		else
		{
			print STDERR "ERROR: too few arguments to create\n";
			&usage (1);
		}
	}
	else {
		# unrecognized option/argument
		print STDERR "ERROR: Unrecognized option: '$_'\n";
		&usage (1);
	}

	$where++;
}

exit (0);

=pod
sub usage: shows how to invoke the command-line program
=cut
sub usage () {
	my $exec = "brinance";

	print "Usage:
	\$ $exec <args>\n
  Accepted args:
     -b --balance -> show current balance
        \$ $exec -b
     -B --datedbalance -> show dated balance
        \$ $exec -B 200306271200
     -c --credit -> apply credit
        \$ $exec -c <amount> <comment>
     -C --datedcredit -> apply dated credit
        \$ $exec -C 200306271200 <amount> <comment>
     -d --debit -> apply debit
        \$ $exec -d <amount> <comment>
     -D --dateddebit -> apply dated debit
        \$ $exec -D 200306271200 <amount> <comment>
     -# -> (as in, a number) all following arguments refer to this account
        \$ $exec -2 <more arguments>
     -n --name -> get the name of the active account
        \$ $exec -4 -n
     -r --create -> create a new account
        \$ $exec -r <account number> <account description>
     -h --help -> help
        \$ $exec -h
     -v --version -> version
        \$ $exec -v\n";

	print "\nSee README for more information.\n";

	exit ($_[0]);
}

sub CLItrans {
	if ( 0 == $arglist[$where+1] ) { $arglist[$where+1] .= ".00"; }

	if ( $arglist[$where+2] && $arglist[$where+1] )
	{  
		my $comment = $arglist[$where+2];
		my $amount = (($credit * 2) - 1) * $arglist[$where+1];

		my $out = &Brinance::trans ( $amount, $comment );

		if ( 0 == $out )
		{
			my $bal = sprintf ("%.2f", &Brinance::balance ());

			if ( $credit )
			{
				print "Balance after credit: $bal\n";
			}
			else
			{
				print "Balance after debit: $bal\n";
			}

			$skipnext = 2;
		}
		elsif ( -1 == $out )
		{
			print STDERR "ERROR: too few arguments to Brinance::trans()\n";
			&usage (1);
		}
		elsif ( -2 == $out )
		{
			print STDERR "ERROR: zero-value transaction\n";
			&usage (1);
		}
		else
		{
			print STDERR "ERROR: undefined output from Brinance::trans(); Check your accounts file..\n";
			print "Exitting..\n";
			exit (0);
		}
	}  
	else
	{  
		print STDERR "ERROR: too few arguments for a transaction\n";
		&usage (1);
	}  
}

sub CLIdatedtrans {
	if ( $arglist[$where+1] && $arglist[$where+1] == 0) { $arglist[$where+1] .= ".00"; }

	if ( $arglist[$where+3] && $arglist[$where+2] && $arglist[$where+1] )
	{
		my $comment = $arglist[$where+3];
		my $date_mod;

		if ( $arglist[$where+1] =~ /^\+(\d+)$/ ) {
			my (undef,$min,$hour,$mday,$mon,$year,undef,undef,undef) = localtime(time + ($1 * 60 * 60 * 24));

			$year += 1900;
			$mon += 1;
			if ($mon  < 10) {$mon  = "0" . $mon;}
			if ($mday < 10) {$mday = "0" . $mday;}
			if ($hour < 10) {$hour = "0" . $hour;}
			if ($min  < 10) {$min  = "0" . $min;}
			$date_mod = $year . $mon . $mday . $hour . $min;
		}
		elsif ( $arglist[$where+1] =~ /^(\d{12})$/ ) {
			$date_mod = $1;
		}
		else { # date is not formatted properly
			print STDERR "ERROR: date not in 12-digit or +<days> format\n";
			&usage (1);
		}

		my $amount = (($credit * 2) - 1) * $arglist[$where+2];

		my $out = &Brinance::trans ( $amount, $comment, $date_mod );

		if ( 0 == $out )
		{
			print "Dated transaction applied: ";

			if ( $date_mod <= $Brinance::now ) {
				print sprintf ("Current balance: %.2f\n", &Brinance::balance ());
			} else {
				print sprintf ("Balance at date $date_mod: %.2f\n", &Brinance::balance($date_mod));
			}

			$skipnext = 3;
		}
		elsif ( -1 == $out )
		{
			print STDERR "ERROR: too few arguments to Brinance::trans()\n";
			&usage (1);
		}
		elsif ( -2 == $out )
		{
			print STDERR "ERROR: zero-value transaction\n";
			&usage (1);
		}
		elsif ( -3 == $out )
		{
			print STDERR "ERROR: invalid date format specified\n";
			&usage (1);
		}
		else
		{
			print STDERR "ERROR: undefined output from Brinance::trans(); Check your accounts file..\n";
			print STDERR "Exitting..\n";
			exit (1);
		}
	}
	else
	{
		print STDERR "ERROR: too few arguments for a dated transaction\n";
		&usage (1);
	}
}
