#!/usr/bin/env perl

use G;
use G::DB::SDB;
use Term::ReadLine;
use POSIX qw(:sys_wait_h);
use Getopt::Std;

use vars qw($opt_l $opt_s $filename $G_INTERNAL_configurator $G_INTERNAL_HASH_OLD $G_INTERNAL_OPT $G_INTERNAL_LOG $G_INTERNAL_CACHE1 $G_INTERNAL_HEADER);


$| = 1;

my $G_INTERNAL_LOG_HEADER = 'use G::DB::SDB;
  my $G_INTERNAL_HASH = sdb_load("G_INTERNAL_OLD");
foreach  my $G_INTERNAL_TMP1 (keys(%{$$G_INTERNAL_HASH})){
    my $G_INTERNAL_TMP2 = $$G_INTERNAL_HASH->{$G_INTERNAL_TMP1};
    if($G_INTERNAL_TMP1 =~ /^\$/){
	$G_INTERNAL_TMP1 =~ s/\$//g;
        ${"$G_INTERNAL_TMP1"} = $G_INTERNAL_TMP2;
    }
    if($G_INTERNAL_TMP1 =~ /^\@/){
	$G_INTERNAL_TMP1 =~ s/\@//g;
        @{"$G_INTERNAL_TMP1"} = @$G_INTERNAL_TMP2;
    }
    if($G_INTERNAL_TMP1 =~ /^\%/){
	$G_INTERNAL_TMP1 =~ s/\%//g;
        %{"$G_INTERNAL_TMP1"} = %$G_INTERNAL_TMP2;
    }
}\n';

if($ARGV[0]){
  if($ARGV[0] =~ /.pl$/){
    system("perl -MG $ARGV[0]");
  }
  elsif($ARGV[0] =~ /.gcf$/){
      funcD($ARGV[0]);
  }
}else{
  my $G_INTERNAL_TERM = Term::ReadLine->new('G_tmp');
  my $G_INTERNAL_ATTRIBS = $G_INTERNAL_TERM->Attribs;

  $G_INTERNAL_ATTRIBS->{catch_signals} = 0;
  $G_INTERNAL_ATTRIBS->{attempted_completion_function} = \&G_INTERNAL_COMPLETION;
  $G_INTERNAL_ATTRIBS->{completion_word} = [map {"$_()"} @G::EXPORT];

  sub G_INTERNAL_COMPLETION {
      my ($text, $line, $start, $end) = @_;
      
      if(substr($line, 0, $start) =~ /^\s*$/){
	  return ($G_INTERNAL_TERM->completion_matches($text,$G_INTERNAL_ATTRIBS->{'filename_completion_function'}),
		  $G_INTERNAL_TERM->completion_matches($text,$G_INTERNAL_ATTRIBS->{'list_completion_function'})
		  );
      }else{
	  return ();
      }
  }

  my $G_INTERNAL_STDIN = $G_INTERNAL_TERM->IN() || *STDIN;
  my $G_INTERNAL_DIRECT = $G_INTERNAL_TERM->OUT() || *STDOUT;

  $SIG{INT} = sub{
      if($G_INTERNAL_TERM->ReadLine eq 'Term::ReadLine::Gnu'){
	  $G_INTERNAL_ATTRIBS->{done} = 1;
  	  $G_INTERNAL_TERM->free_line_state(); 
	  $G_INTERNAL_TERM->cleanup_after_signal();
	  print $G_INTERNAL_DIRECT "SIGINT: use \"quit\" to exit.\n\n";
      }
  };
  
  my $G_INTERNAL_INSTANCE = new G("blessed");
  $G_INTERNAL_INSTANCE->loaded_msg();
  
  getopts('l');
  $G_INTERNAL_OPT = $opt_l;
  
  my $G_INTERNAL_HASH_OLD = {};
  G_INTERNAL_HASH_OLD->{dummy} = 1;
  my $G_INTERNAL_CACHE1 = '';
  my $G_INTERNAL_HEADER = '> ';
  my $G_INTERNAL_LOG = '';
  unless (-e _sdb_path() . 'G_INTERNAL_OLD'){
    sdb_save(\$G_INTERNAL_HASH_OLD, "G_INTERNAL_OLD");
  }
  my $G_INTERNAL_HASH = sdb_load('G_INTERNAL_OLD');
  
  
  foreach  my $G_INTERNAL_TMP1 (keys(%{$$G_INTERNAL_HASH})){
    my $G_INTERNAL_TMP2 = $$G_INTERNAL_HASH->{$G_INTERNAL_TMP1};
    if($G_INTERNAL_TMP1 =~ /^\$/){
      $G_INTERNAL_TMP1 =~ s/\$//g;
      ${"$G_INTERNAL_TMP1"} = $G_INTERNAL_TMP2;
    }
    if($G_INTERNAL_TMP1 =~ /^\@/){
      $G_INTERNAL_TMP1 =~ s/\@//g;
      @{"$G_INTERNAL_TMP1"} = @$G_INTERNAL_TMP2;
    }
    if($G_INTERNAL_TMP1 =~ /^\%/){
      $G_INTERNAL_TMP1 =~ s/\%//g;
      %{"$G_INTERNAL_TMP1"} = %$G_INTERNAL_TMP2;
    }
  }
  do{
    my $G_INTERNAL_TMP;
    $G_INTERNAL_INPUT = $G_INTERNAL_TERM->readline('G >');

    my $G_INTERNAL_SHFLAG = 0;

    foreach my $G_INTERNAL_COMMAND (qw(ls pwd cat more less head tail uniq
				       wc diff compress uncompress gzip gunzip
				       zcat tar ln find cp mv rm touch nkf tee
				       which jobs date cal whoami w finger chfn
				       history alias unalias type echo env source 
				       printenv su df du uptime uname
				       dmesg mount ps rpm man info kill ping ifconfig
				       setenv export lv display convert free
				       gimp firefox dig traceroute emacs scp
				       rsh ftp sudo mysql psql make
				       ruby sh python vi R wget curl
				       )){

	if($G_INTERNAL_INPUT =~ /^\s*$G_INTERNAL_COMMAND\s*/){
	    $G_INTERNAL_SHFLAG = 1;
	    my $G_INTERNAL_SIGINT = 0;
	    eval{
		eval{
		    system($G_INTERNAL_INPUT);
		};
		die($@) if($@);
	    };

	    warn $@ if($@);

	    last;
	}
    }

    if($G_INTERNAL_SHFLAG == 1){
	#do nothing, already done.
    }
    elsif($G_INTERNAL_INPUT =~ /^\s*exit/){
	quit();
    }
    elsif($G_INTERNAL_INPUT =~ /^\s*cd\s*(\S+)/){
	$G_INTERNAL_INPUT = $1;

      chdir ($G_INTERNAL_INPUT) || print $G_INTERNAL_INPUT, ": ", $!, "\n";
    }
    elsif($G_INTERNAL_INPUT =~ /^\s*makelog/){
      $G_INTERNAL_OPT = 1;
    }
    elsif($G_INTERNAL_INPUT =~ /^\s*rmlog/){
      $G_INTERNAL_OPT = 0;
    }
    elsif($G_INTERNAL_INPUT =~ /^\s*mokkori/){
      while(1){
	$G_INTERNAL_INPUT = $G_INTERNAL_TERM->readline('MOKKORI? ');
	last if($G_INTERNAL_INPUT =~ /^\s*mokkori/);
      }
    }
    else{ 
      $G_INTERNAL_CUT = substr($G_INTERNAL_INPUT, -1,1);
      if($G_INTERNAL_CUT eq '\\'){
	my $G_INTERNAL_I = 1;
	do{
	  $G_INTERNAL_CUT = substr($G_INTERNAL_INPUT, -1,1);
	  if($G_INTERNAL_CUT eq '\\'){
	    chomp($G_INTERNAL_INPUT);
	    chop($G_INTERNAL_INPUT);
	    $G_INTERNAL_INPUT1 = "$G_INTERNAL_INPUT\n";
	    $G_INTERNAL_CACHE1 .= $G_INTERNAL_INPUT1;
	    $G_INTERNAL_INPUT = $G_INTERNAL_TERM->readline('next >>');
	  }
	  else{
	    $G_INTERNAL_INPUT1 = "$G_INTERNAL_INPUT\n";
	    $G_INTERNAL_I = 0;
	  }
	}while($G_INTERNAL_I == 1);
      }
      $G_INTERNAL_CACHE1 .= $G_INTERNAL_INPUT;

      $G_INTERNAL_TMP = eval{
	  local $SIG{'INT'} = sub{warn("SIGINT: Interrupted by user.");die();};
	  my $return = eval($G_INTERNAL_CACHE1);
	  die($@) if ($@);
	  return $return;
      };

      $G_INTERNAL_LOG .= "$G_INTERNAL_CACHE1\n";
      $G_INTERNAL_TERM->addhistory($G_INTERNAL_CACHE1);
      if($G_INTERNAL_CACHE1 =~ /^\s*\$/){		    
	@G_INTERNAL_ARRAY = split(/=/,$G_INTERNAL_CACHE1);
	$G_INTERNAL_ARRAY[0] =~ s/ //g;
	$G_INTERNAL_KEY = $G_INTERNAL_ARRAY[0];
	$G_INTERNAL_ARRAY[0] =~ s/\$//g;
	$G_INTERNAL_HASH_OLD->{"$G_INTERNAL_KEY"} = ${"$G_INTERNAL_ARRAY[0]"};
      }
      elsif($G_INTERNAL_CACHE1 =~ /^\s*\@/){		    
	@G_INTERNAL_ARRAY = split(/=/,$G_INTERNAL_CACHE1);
	$G_INTERNAL_ARRAY[0] =~ s/ //g;
	$G_INTERNAL_KEY = $G_INTERNAL_ARRAY[0];
	$G_INTERNAL_ARRAY[0] =~ s/\@//g;
	$G_INTERNAL_HASH_OLD->{"$G_INTERNAL_KEY"} = \@{"$G_INTERNAL_ARRAY[0]"};
      }
      elsif($G_INTERNAL_CACHE1 =~ /^\s*\%/){		    
	@G_INTERNAL_ARRAY = split(/=/,$G_INTERNAL_CACHE1);
	$G_INTERNAL_ARRAY[0] =~ s/ //g;
	$G_INTERNAL_KEY = $G_INTERNAL_ARRAY[0];
	$G_INTERNAL_ARRAY[0] =~ s/\%//g;
	$G_INTERNAL_HASH_OLD->{"$G_INTERNAL_KEY"} = \%{"$G_INTERNAL_ARRAY[0]"};
      }

      $G_INTERNAL_CACHE1 = "";

      if ($@){
	  my $G_INTERNAL_ERROR_MSG = $@;
	  $G_INTERNAL_ERROR_MSG =~ s/(.*)\(eval \d+\) (.*)/$1$2/g;

	warn $G_INTERNAL_ERROR_MSG;
	reset_settings();
      }elsif($G_INTERNAL_TMP eq ''){
	reset_settings();
      }elsif($G_INTERNAL_TMP =~ /^\d+/){
	reset_settings();
	print "\n";
      }else{
	reset_settings();
      }
      
    }
  }while(1);    
  
sub reset_settings{
    $G_INTERNAL_CACHE1 = '';
    $G_INTERNAL_HEADER = '> ';
}


sub quit{
    print "  save value ?  y/n (or cancel) ?\n";

    my $n = 1;
    do{
      my $G_INTERNAL_INPUT2 = $G_INTERNAL_TERM->readline('quit >>');

      if($G_INTERNAL_INPUT2 eq 'y'){
	sdb_save(\$G_INTERNAL_HASH_OLD,'G_INTERNAL_OLD');
	if($G_INTERNAL_OPT == 1){
	  open(FILE,"> G_INTERNAL.log");
	  print (FILE "#####HEADER#####\nuse G;\n$G_INTERNAL_LOG_HEADER\n#####LOG#####\n$G_INTERNAL_LOG");
	  close(FILE);
	}
	$n = 0;
      }
      elsif($G_INTERNAL_INPUT2 eq 'cancel'){
	  return;
      }
      elsif($G_INTERNAL_INPUT2 eq 'n'){
	  $n = 0;
      }
      else{
	print "select 'y', 'n', or 'cancel'\n";
      }
    }while($n);

    opendir(DIR, $ENV{HOME} . '/.glang/');
    foreach my $file (readdir(DIR)){
	next unless($file =~ /^cache-/);

	$file = $ENV{HOME} . '/.glang/' . $file;
	my $mtime = (stat($file))[9];

	if(time() - $mtime > 3600 * 24 * 31){
	    unlink($file);
	}
    }
    closedir(DIR);

    exit;
}

}






















