package ACIS::MiLa::DataBuilder;

use strict;
use vars qw( $stack $res $self $inputpos );

sub close_statement();
sub open_statement($);
sub open_statement_list($);
sub add_to_context($);


# $stack = [ { prefix => '', data => [] } ];
# $res   = $stack -> [0] {data};


sub new {
  my $class = shift;
  my $data  = shift || [];

  $res = $data;

  my $self = {
              res   => $data,
              stack => 
              [ { prefix => '', data => $data } ],
             };

  bless $self, $class;
}

sub result {
  $self = shift;
  return $self -> {res};
}

sub token_space {
  $self  = shift;
  $stack = $self -> {stack};
#  $data  = $self -> {res};

  my $space = shift;
  $inputpos = shift;
  
  space( $space );
}

sub token_word {
  $self  = shift;
  $stack = $self -> {stack};

  my $word = shift;
  $inputpos = shift;

  add_to_context $word;
}

sub token_string {
  $self  = shift;
  $stack = $self -> {stack};

  my $string = shift;
  $inputpos = shift;

  add_to_context $string;
}


sub token_eof {
  $self  = shift;
  $stack = $self -> {stack};

  shift; ### placeholder, usually ``1''
  $inputpos = shift;

  EOF ();
}
  


sub last_stacked  ()  { $stack -> [ $#$stack ]; }
sub push_to_stack (@) { push @$stack, @_; }
sub pop_from_stack()  { pop @$stack; }




sub space {
  my $s          = shift;
  my $must_match = shift;

#  print "space: '$s'" , ($must_match) ? ", must_match" : "", "\n";

  my $c = last_stacked;

  my $s_len = length( $s );

  my $level = $c -> {level};
  my $type  = 'st';
  
  if ( not defined $level ) {
    $type = 'list';
    $level = $c -> {prefix};
  }

#  print "level: '$level'\n";

  if ( length( $level ) == $s_len ) {

    if ( $must_match ) {
#      print "space level matched at a $type\n";
    }

    if ( $type eq 'list' ) {
      if ( $s ne '' ) {
      }

    } else {
      close_statement;
    }

    open_statement $s;

  } elsif ( length $level < $s_len ) {
    
    if ( $must_match ) {
      die "a statement indentation doesn't match any of the open constructs at $inputpos\n";
    }

    if ( $type eq 'st' ) {
      open_statement_list $s;
    }
    open_statement $s;

  } else {
    if ( close_statement ) {
      return space( $s, 1 );  

    } else {
      die "internal error: somehow close_statement failed or tried to close unclosable at $inputpos\n";
    }
  }
}


sub EOF {
  my $c = last_stacked;
  while ( $c and 
          (
           not $c -> {prefix}
           or  $c -> {prefix} ne '' 
          ) ) {
    close_statement;
    $c = last_stacked;
  }
  close_statement;
}






sub open_statement ($) {
  my $level = shift;
  my $stmt  = [];
  my $desc  = { level => $level, data => $stmt, type=>'statement' };
  add_to_context $stmt;
  push_to_stack $desc;
}

sub open_statement_list ($) {
  my $level = shift;
  my $stmt  = [];
  my $desc  = { prefix => $level, data => $stmt, type=>'list' };
  add_to_context $stmt;
  push_to_stack $desc;
}

sub close_statement() {
  my $desc = last_stacked;

  if ( not $desc ) { 
    return 0;
  }

  my $type;
  if ( defined $desc -> {level} ) {
#    $type = 'statement';
    pop_from_stack;

  } elsif ( defined $desc -> {prefix} ) {
#    $type = 'list';
    pop_from_stack;
#    print "closed $type\n";
    return close_statement;

  } else { die; }

#  print "closed $type\n";
  return 1;
}    

sub add_to_context ($) {
  my $thing = shift;
  my $desc = last_stacked;
  my $data = $desc -> {data};
  push @$data, $thing;
}




sub test_token_list {
  my @tokens = (
  '', 'namespace', 'amf',
  '  ', 'uri', 'http://amf.openlib.org',
  '     ', 'schema', 'http://amf.openlib.org/2002/schema',
  '  ',
       'url', 'http://amf.openlib.org/',
  ' ', 'about', 'amf',
  '', 'file',
  '!'
               );

  foreach ( @tokens ) {
    if ( m/^!$/ ) {
      print "\nEOF\n";
      EOF( $_ );
      
    } elsif ( m/^\s*$/ ) {
      space( $_ );
      
    } else { 
      print " $_\n";
      add_to_context( $_ );
    }
  }
 
}



sub show_result {

  require Data::Dumper;
  eval 'use Data::Dumper';

#  print "Stack: ----\n",
#    Dumper( $stack ),
#      "\n-----------\n";
  
  print "Result: ---\n",
    Dumper( $res ),
      "\n-----------\n";

  return;
}



sub test_issue_direct_building_commands {
  open_statement '';
  add_to_context 'namespace';
  add_to_context 'amf';
  open_statement_list '  ';
  open_statement '  ';
  add_to_context 'uri';
  add_to_context 'http://amf.openlib.org';
  open_statement_list '    ';
  open_statement '    ';
  add_to_context 'schema';
  add_to_context 'http://amf.openlib.org/2002/schema';
  close_statement;
  open_statement '  ';
  add_to_context 'url';
  add_to_context 'http://amf.openlib.org/';
  
  close_statement;
  close_statement;
  close_statement;

  open_statement '';
  add_to_context 'about';
  add_to_context 'amf';
  close_statement;

}

  
1;
  
