#!/usr/bin/perl -w

use lib 'lib';
use warnings;
use strict;

use Getopt::Compact;
use Pye;
use JSON;
use Term::ANSIColor;
use Text::SpanningTable;

$MongoDB::Cursor::slave_okay = 1;

=head1 NAME
 
pye - Inspect logs generated by Pye

=head1 VERSION

version 1.000000

=head1 SYNOPSIS

In the command line:

	# show list of latest 10 sessions
	$ pye

	# show complete log for a specific session ID (say "123")
	$ pye -S 123

	# log a message for a specific session ID (say "123") with complex data
	$ pye -S 123 -m "some log message" -D '{ "some": "data" }'
 
=head1 DESCRIPTION

C<pye> is a command line utility for reading and inspecting logs generated by
the L<Pye> module.

It allows viewing sessions in the log, reading the entire log of a session,
and even adding messages and data to the log.

If you're using C<Pye> to save logs from more than one application on a server,
I find it useful to create aliases to C<pye> with different options to quickly
inspect the log for every application. For example, say I have an application
called "myapp", and another one called "myscript", which save logs to the same
database, but in different collections. I might create the following bash aliases:

	alias myapp='pye -d logs -l myapp_logs -s myapp_sessions'
	alias myscript='pye -d logs -l myscript_logs -s myscript_sessions'

=head1 OPTIONS

=head2 -H, --host

The MongoDB database host. Defaults to "localhost".

=head2 -p, --port

The MongoDB database port. Defaults to 27017.

=head2 -d, --database

The name of the database. Defaults to "logs".

=head2 -l, --log_coll

The name of the collection where log messages are stored. Defaults to "logs".

=head2 -s, --session_coll

The name of the collection where session data is stored. Defaults to "sessions".

=head2 -S, --session_id

The session ID to display or log a message for. Optional.

=head2 -m, --message

The message to log to the database (requires session ID to be supplied too). Optional.

=head2 -D, --data

A JSON structure to attach to the message. Optional.

=cut

my $gopt = Getopt::Compact->new(
	name => 'pye',
	struct => [
		[[qw/H host/], 'The host to connect to, defauls to localhost', ':s'],
		[[qw/p port/], 'The port to connect on, defaults to 27017', ':s'],
		[[qw/d database/], 'The database to use, defaults to logs', ':s'],
		[[qw/l log_coll/], 'The collection where logs are stored, defaults to logs', ':s'],
		[[qw/s session_coll/], 'The collection where sessions are stored, defaults to sessions', ':s'],
		[[qw/S session_id/], 'The session_id to display or log a message for', ':s'],
		[[qw/m message/], 'An optional message to log to the database, requires session_id', ':s'],
		[[qw/D data/], 'An options hash to attach to the message, in JSON', ':s'],
	]
);
my $opts = $gopt->opts;
my %options = (
	host => 'localhost',
	port => 27017,
	database => 'logs',
	log_coll => 'logs',
	session_coll => 'sessions'
);
@options{grep(defined $opts->{$_}, keys(%$opts))} = grep(defined $_, values(%$opts))
	if $opts && ref $opts eq 'HASH' && scalar keys %$opts;

$options{log_db} = delete($options{database});

my $pye = Pye->new(%options);
my $json = JSON->new->utf8->pretty;

if ($options{session_id}) {
	if ($options{message}) {
		my $data;
		$data = decode_json($options{data}) if $options{data};
		$pye->log($options{session_id}, $options{message}, $data);
	}

	my @entries = $pye->session_log($options{session_id});
	if (scalar @entries) {
		foreach my $doc (@entries) {
			print color 'bold red';
			print $doc->{date}->ymd, ', ', $doc->{date}->hms, ': ';
			print color 'reset';
			print $doc->{text}, "\n";
			if ($doc->{data}) {
				print color 'green';
				my @rows = split(/\n/, $json->encode($doc->{data}));
				for (my $i = 0; $i <= $#rows; $i++) {
					chomp($rows[$i]);
					print "\t $rows[$i]";
					#print "\n" if $i < $#rows;
					print "\n";
				}
			}
			print "\n";
		}
	} else {
		print "Nothing found\n";
	}
} else {
	my @sessions = $pye->list_sessions;

	if (scalar @sessions) {
		print "Latest sessions logged:\n";
		print color 'bold';
		my $t = Text::SpanningTable->new(14, 12, 24); $t->newlines(1);
		print $t->hr('top');
		print $t->row('Date', 'Time', 'Session ID');
		print $t->dhr;
		print color 'reset';
		foreach (@sessions) {
			print $t->row($_->{date}->ymd, $_->{date}->hms, $_->{_id});
		}
		print color 'bold';
		print $t->hr('bottom');
		print color 'reset';
	} else {
		print "No sessions in log\n";
	}
}

=head1 SEE ALSO

L<Pye>

=head1 BUGS AND LIMITATIONS

Please report any bugs or feature requests to
C<bug-Pye@rt.cpan.org>, or through the web interface at
L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Pye>.
 
=head1 SUPPORT
 
You can find documentation for this module by invoking it with
the C<-h> switch:
 
	pye -h
 
=head1 AUTHOR
 
Ido Perlmuter <ido@ido50.net>
 
=head1 LICENSE AND COPYRIGHT
 
Copyright (c) 2013, Ido Perlmuter C<< ido@ido50.net >>.
 
This module is free software; you can redistribute it and/or
modify it under the same terms as Perl itself, either version
5.8.1 or any later version. See L<perlartistic|perlartistic>
and L<perlgpl|perlgpl>.
 
The full text of the license can be found in the
LICENSE file included with this module.
 
=head1 DISCLAIMER OF WARRANTY
 
BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
NECESSARY SERVICING, REPAIR, OR CORRECTION.
 
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
 
=cut
