#!/usr/bin/perl

use strict;
use warnings;
use Data::Dumper;
use Expect;

my $debug = 0;

if (!defined($ARGV[0]) || !$ARGV[0]) {
  die "Argumentem je adresar, kam se bude vse ukladat\n";
}

my $arch = 'i386';
if (defined($ENV{"ARCH"}) && $ENV{"ARCH"}) {
  $arch = $ENV{"ARCH"};
}

# Delete output dir
system("rm ".$ARGV[0]."/0*.txt");

my $menu_hash = {};
parse_kconfig('./arch/'.$arch.'/Kconfig',$menu_hash,0);

my $exp = Expect->spawn("make",("config"));
$exp->log_file("expect.log","w");
$exp->log_stdout(0);
#$exp->exp_internal(1);
my $timeout = 60;
my $out = $ARGV[0];
my $count = 1;
my $prev_choice = '';
my $prev_config = '';

# Initialize...
my $txt = '';
open(MENU,">/dev/null");

while (1) {
  $exp->expect($timeout,
    ['choice\[\d+(\-\d+\??)?\]:' , \&options,"1"],
    ['\[Y\/n(\/\?)?\]' , \&config,'Y'],
    ['\[Y\/n\/m(\/\?)?\]' , \&config,'Y'],
    ['\[Y\/m(\/\?)?\]' , \&config,'Y'],
    ['\[N\/y(\/\?)?\]' , \&config,'Y'],
    ['\[N\/m\/\?\]' , \&config,'m'],
    ['\[N\/m\/y(\/\?)?\]' , \&config,'Y'],
    ['\[M\/n\/y(\/\?)?\]' , \&config,'Y'],
    ['\[M\/n\/\?\]' , \&config,'m'],
    ['\[M\/y\/\?\]' , \&config,'Y'],
    ['\[Y\/\?\]' , \&config,'Y'],
    ['\[\]' , \&config,'Y'],
    ['\[-?\d+\]( \(NEW\))?' , \&config, ""],
    ['\[\d+\w+\]( \(NEW\))?' , \&config, ""],
    ['\[([\/\.]\w+)+\]( \(NEW\))?' , \&config, ""], # PATH
    ['\[[\w\d\-]+\]( \(NEW\))?' , \&config, ""], # ENCODING
    ['\[640x480@60\]( \(NEW\))?' , \&config, ""], # VESA DEF MODE
    ['\[\d+x\d+\]( \(NEW\))?' , \&config, ""],
    ['^\s*\#\s*', \&config, ""],
  );
}

# funkce na parsovani

sub options {
  my $exp = shift;
  my $send = shift;

  my $snd = 1;
  if ($exp->after =~ /^\s*1\s*$/) {
    $snd = 0;
  } elsif ($exp->after =~ /[^\s]+/) {
    if ($debug & 2) {
      print STDERR "CAfter: ".$exp->after."\n";
    }
  }

  my @tmp = split("\n",$exp->before());

  shift(@tmp); # Odstranime predeslou vlozenou hodnotu

  if ($tmp[0] =~ /^\s*$/) {
    shift(@tmp);
  }

  if ($tmp[scalar(@tmp) -1] =~ /^\s*$/) {
    pop(@tmp);
  }

  my $config_count = 0;

  if ($exp->match() =~ /\[1-(\d+)/) {
    $config_count = $1;
  }

  if ($config_count && (scalar(@tmp) - 1 > $config_count)) {
    my @configs = splice(@tmp,0,scalar(@tmp) - 1 - $config_count);
    zpracuj_config(@configs);
  }

  if ($exp->match() =~ /choice\[1\]/) {
    $snd = 0;
  }

  if ($tmp[0] =~ /^(\s*)(.+)\s*$/) {
    my $times = length($1)/2 + 1;
    my $choice = $2;
    $choice =~ s///g;
    chomp($choice);
    if ($prev_choice eq $choice) {
      if ($debug & 1) {
        print STDERR "CDUP: ".$choice."\n";
      }
      $exp->send($send."\n");
      return exp_continue;
    } else {
      $prev_choice = $choice;
    }
    print MENU '>' x $times;

    print MENU ' '.$choice."\n";
    $times++;
    for (my $j = 1; $j < scalar(@tmp); $j++) {
      if ($tmp[$j] =~ /^\s*>?\s*\d\.\s*(.+)\s\(([^\)]+)\)\s*$/) {
        print MENU '>' x $times;
        print MENU ' [[kernel:config_'.lc($2).'|'.$1.']]'."\n";
      }
    }
  }
  if ($snd) {
    $exp->send($send."\n");
  }
  return exp_continue;
}


sub config {
  my $exp = shift;
  my $send = shift;

  my $snd = 1;
  if ($exp->after =~ /^\s*y\s*$/) {
    $snd = 0;
  } elsif ($exp->after =~ /[^\s]+/) {
    if ($debug & 2) {
      print STDERR "After: ".$exp->after."\n";
    }
  }

  my @tmp = split("\n",$exp->before());

  &zpracuj_config(@tmp);

  if ($snd) {
    $exp->send($send."\n");
  }
  return exp_continue;
}

sub zpracuj_config {
  my @tmp = @_;

  my $menu = '';
  my $menu_indent = 0;
  for (my $i = 0; $i < scalar(@tmp); $i++) {
    $tmp[$i] =~ s///g;
    if ($tmp[$i] =~ /^\s*\*\s*$/) {
      next;
    } elsif ($tmp[$i] =~ /^(\s*)\*\s*(.+[^\s].+)\s*$/) {
      $menu = $2;
      $menu_indent = length($1)/2 + 1;
      if (($menu_indent == 1) && defined($menu_hash->{$menu})) {
        undef($menu_hash->{$menu});
        close(MENU);
        open(MENU,"> ". $out.'/'.
          sprintf("%03d",$count)."_".create_filename($menu)) or die "Can't open file ".sprintf("%03d",$count)."_".create_filename($menu)."\n";
        $menu = '';
        $menu_indent = 0;
        $count++;
      } else {
        print MENU '>' x $menu_indent;
        print MENU ' '.$menu."\n";
        $menu = '';
        $menu_indent = 0;
      }
    } elsif ($tmp[$i] =~ /^(\s*)(.+)\s+\(([^\)]+)\)\s*(\[[^\]]+\]\s*y)?\s*(\[.+\])?\s*$/i) {
      my $times = length($1)/2 + 1;
      if ($prev_config eq $3) {
        if ($debug & 1) {
          print STDERR "DUP: ".$3."\n";
        }
      } else {
        $prev_config = $3;
      }
      print MENU '>' x $times;
      print MENU ' [[kernel:config_'.lc($3).'|'.$2.']]'."\n";
    } elsif ($tmp[$i] =~ /configuration written to \.config/) {
      close(MENU);
      exit;
    } else {
      if ($debug & 4) {
        if ($tmp[$i] !~ /^\s*[y1m]?\s*$/i) {  
          print STDERR "NEvim co s tim: ".$tmp[$i]."\n";
        }
      }
    }
  }
}

sub create_filename {
  my $menu = shift;
  $menu =~ s/ /_/g;
  $menu =~ s/\//-/g;
  return lc($menu).'.txt';
}

# Vytvori hash s polozkami v hlavnim menu

sub parse_kconfig {
  my $path = shift;
  my $menu = shift;
  my $deep = shift;
  my $in;

  open($in,$path) or die "Can't open ".$path."\n";

  while (my $line = <$in>) {
    if ($line =~ /^source\s+"?([^\s"]+)"?\s+$/) {
      parse_kconfig($1,$menu,$deep);
    } else {
      # Tady musim parsovat menu
      if ($line =~ /^\s*menu\s+["']([^"']+)["']/) {
        my $m = $1;
        if ($deep == 0) {
          $menu->{$m} = 1;
        }
        $deep++;
      }
      if ($line =~ /^\s*endmenu/) {
        $deep--;
      }
    }
  }
  close($in);
}

