#!/usr/bin/perl -w 
#
# Zymonic Business Process and Information Management System
# Copyright Zednax Limited 2008 -
# For Authors and Changelog see the subversion history

BEGIN
{
    use Zymonic::Utils qw(death_handler clean rethrow_exception update_debug_metadata);
    $main::SIG{__DIE__} = \&death_handler;

    # Warnings will cause the debugger to drop 'stop' so further
    # debugging can be done.
    no warnings;    # DB::single is only needed in -d mode
    $SIG{__WARN__} = sub { print join( " ", @_ ); $DB::single = 1 };
}

use strict;
use warnings;

use Zymonic;
use Zymonic::Toolkit;
use Zymonic::DB::none;

package main;

# need to setup caches as with MP/cgi handlers
$Zymonic::object_cache = { 'Zymonic::TableInclude' => {}, 'Zymonic::RelationshipPermissions' => {}, };

my $usage = "Usage:\nzymonic_toolkit.pl [MODULE] [COMMAND] [COMMAND ARGUMENTS]\nOR\nzymonic_toolkit.pl [CONFIGFILE]\n";

# set binmode for STDOUT and STDERR to handle unicode
binmode STDOUT, ':utf8';
binmode STDERR, ':utf8';

my $module = $ARGV[0] || '';
my $method = $ARGV[1] || '';

my $mo;
my $DB;

%Zymonic::ENV = %ENV;

# Load requested module (to be able to get args)
if ( !$module )
{
    print $usage;
    print "No module or configfile found on command line - add a module name to get further help.\n";
    print "\nAvailable modules:\n";
    foreach my $toolkit_module ( Zymonic::Toolkit::get_available_toolkit_modules() )
    {
        my $toolkit_description = '';
        eval {
            my $toolkit_def = "Zymonic::Toolkit::$toolkit_module"->definition();
            $toolkit_description =
              ( $toolkit_def && $toolkit_def->{ShortDescription} ? $toolkit_def->{ShortDescription}->{content} : '' );
        };
        print "* $toolkit_module - $toolkit_description\n";
    }
    exit(0);
}
else
{
    # Create a command line session object and Field Factory
    $Zymonic::field_factory = Zymonic::FieldFactory->new();

    # Use a 'none' DB object to start with
    $DB = Zymonic::DB::none->new();

    my $session = Zymonic::Session->new( module => 'CLI', ident => '', DB => $DB, request_source => 'zymonic_toolkit' );
    $Zymonic::session = $session;

    # load toolkit, from configfile if set
    $mo = Zymonic::Toolkit->new(
        ( -f $module ? ( configfile => $module ) : ( module => $module ) ),
        DB      => $DB,
        session => $session,

        # send through method so we know what method is to be run
        method => $method || '',
    );

    # check whether modules/method are set from within it
    $module = $mo->get_module();
    $method = $mo->get_method();

    unless ( ref($mo) eq 'Zymonic::Toolkit::' . $module )
    {
        print $usage;
        print "Module $module not found.\n";
        exit(0);
    }

    if ( $method and !$mo->can($method) )
    {
        print $usage;
        print "Command $method is not provided by $module.\n";
        print "Available commands: " . join( ", ", $mo->commands ) . "\n";
        exit(0);
    }
    elsif ( !$method )
    {
        print $usage;
        print "Available commands: " . join( ", ", $mo->commands ) . "\n";
        exit(0);
    }
}

# process any commands (add a pre-process step to get options??)
if ( $mo->validate_fields($method) )
{
    $Zymonic::session->session_debugs();
    eval {
        $mo->$method();
        1;
    } or do
    {
        my $exception = $@;
        $mo->log( $mo->ll_exception($exception) );
        if ( ref($exception) && $exception->isa('Zymonic::Exception::Toolkit::ForceStop') )
        {
            # for force stop errors, print out the message to the user
            print $mo->ll_exception($exception) . "\n";
        }
        else
        {
            # otherwise rethrow for death handler
            rethrow_exception($exception);
        }
    };

    update_debug_metadata(
        {
            type        => 'toolkit',
            zname       => $module . '_' . $method,
            displayname => $module . ' ' . $method,
        }
    );

    my $completed_message = $mo->get_completed_message();
    print "$completed_message\n" if $completed_message;

}
else
{
    $mo->usage_and_errors($method);
}

# Explicitly destroy session to trigger closing methods
$Zymonic::session = undef;
