#!/usr/bin/perl
#
# $Id: metabrik 362 2014-11-30 11:14:00Z gomor $
#
use strict;
use warnings;

use FindBin;

BEGIN {
   my $home_local = $ENV{HOME}.'/perl5';

   push @INC, $home_local; # CPAN Perl modules "standard" directory
   push @INC, "$FindBin::Bin/../lib"; # Metabrik Perl modules
   push @INC, "$FindBin::Bin/../cpan"; # CPAN Perl modules Metabrik requires
   push @INC, "$FindBin::Bin/../repository"; # Metabrik main repository for Briks

   # Check for local::lib variables
   eval('use local::lib "'.$home_local.'"');
   if ($@) {
      die("[F] metabrik: unable to use local::lib:\n\n".
          "ERROR: $@\n"
      );
   }

   # We "manually" search for Term::ReadLine modules because 
   # it is invalid to try to `use' or `require' it directly.
   my $have_term_readline_gnu = 0;
   my $have_term_readline_perl = 0;
   for my $inc (@INC) {
      if (-f "$inc/Term/ReadLine/Gnu.pm") {
         $have_term_readline_gnu++;
      }
      if (-f "$inc/Term/ReadLine/Perl.pm") {
         $have_term_readline_perl++;
      }
   }

   # We search for metabrik-cpanm in PATH
   my $have_metabrik_cpanm = 0;
   for my $path (split(':', $ENV{PATH})) {
      if (-f "$path/metabrik-cpanm") {
         $have_metabrik_cpanm = 1;
         last;
      }
   }

   if (! $have_metabrik_cpanm) {
      die("[F] metabrik: add the bin directory to your PATH:\n\n".
          'export PATH=$PATH:'.$FindBin::Bin.
          "\n\n"
      );
   }

   # Check for Term::ReadLine capabilities
   if (! defined($ENV{PERL_RL})) {
      if ($have_term_readline_gnu) {
         die("[F] metabrik: add the following to your shell .rc file:\n\n".
             "export PERL_RL=Gnu".
             "\n\n"
         );
      }
      elsif ($have_term_readline_perl) {
         die("[F] metabrik: add the following to your shell .rc file:\n\n".
             "export PERL_RL=Perl".
             "\n\n"
         );
      }
   }

   # Check and install required dependences
   eval("use Lexical::Persistence;");
   if ($@) {
      print("[+] metabrik: installing required dependencies...\n");
      system("metabrik-cpanm Lexical::Persistence");
      print("[+] metabrik: installing required dependencies...done\n");
   }

   # Everything should be fine now, but we prefer to check anyway.
   eval("use Metabrik::Core::Context;");
   if ($@) {
      die("[F] metabrik: you have to set PERL5LIB environment variable like:\n\n".
          'shell$ export PERL5LIB=/path/to/metabrik/lib'.
          "\n\n".
          "ERROR: $@\n"
      );
   }
}

use Getopt::Long;

# Default values
my %lopts = (
   verbose => 2,
   debug => 0,
   no_splash => 0,
);
GetOptions(
   "script=s" => \$lopts{script},
   "rc=s" => \$lopts{rc},
   "verbose=i" => \$lopts{verbose},
   "debug=i" => \$lopts{debug},
   "no-splash" => \$lopts{no_splash},
) or usage();

my $context = Metabrik::Core::Context->new;

$context->brik_init
   or die("[F] metabrik: context init: failed\n");

$context->set('core::log', 'level', $lopts{verbose});

$context->set('core::log', 'debug', $lopts{debug});
$context->set('core::context', 'debug', $lopts{debug});
$context->set('core::shell', 'debug', $lopts{debug});
$context->set('core::global', 'debug', $lopts{debug});

if (defined($lopts{script})) {
   $context->use('shell::script')
      or die("[F] metabrik: use: shell::script: failed\n");

   if ($lopts{rc}) {
      $context->set('shell::rc', 'rc_file', $lopts{rc})
   }
   $context->set('shell::script', 'debug', $lopts{debug});
   $context->set('shell::script', 'file', $lopts{script});

   my $lines = $context->run('shell::script', 'load')
      or die("[F] metabrik: run: shell::script: load: failed\n");

   $context->run('shell::script', 'exec', $lines)
      or die("[F] metabrik: run: shell::script: exec: failed\n");
}
else {
   $context->use('shell::rc')
      or die("[F] metabrik: use: shell::rc: failed\n");

   if ($lopts{rc}) {
      $context->set('shell::rc', 'rc_file', $lopts{rc})
   }
   $context->set('shell::rc', 'debug', $lopts{debug});

   unless ($lopts{no_splash}) {
      $context->run('core::shell', 'splash')
         or die("[F] metabrik: run: core::shell: splash: failed\n");
   }

   $context->run('core::shell', 'cmdloop');
}

exit(0);

sub usage {
   print<<EOF

Usage: metabrik [options]

   --script <file>       execute given script
   --no-splash           don't print the splash screen
   --rc <file>           use specified rc file (default: ~/.metabrik_rc)
   --verbose <0|1|2|3>   verbosity level (default: 2)
   --debug <0|1>         enable debugging (default: 0)

EOF
;

   exit(0);
}
