# ----------------- Using HTML::TokeParser ----------------- #

$FirstTime = 1;
@FullResult = undef;

sub BuildArray {
  use strict;
  my($arg,@files) = @_;
  my($file,@result);

  if ($::FirstTime) {
    while (@files) {
      $file = shift @files;
      push(@::FullResult, &BuildResult(&ParseFile($file),$file)) if $file;
    }
    $::FirstTime = 0;
  }
  $arg =~ s/.* //;
  @result = grep(/<$arg/i, @::FullResult);
  return @result;
}

sub GetArray {
  use strict;
  my($file,@array) = @_;
  my(@list,@result,$f,$n,$t);

  @list = grep /^$file:/, @array;

# The list is of the form filename:line_number:text
# Return just the text part for matching files

  foreach (@list) {
    ($f,$n,$t) = split(/:/,$_,3);
    push(@result,$t);
  }
  
  return @result;
}

sub BuildResult {
    use strict;
    my $result = shift;
    my $file = shift;
    my $out = "";
    my($r,$stag,$etag);

    foreach $r (@$result) {
      next unless $r->{tag};
      $stag = "<".$r->{tag};
      if (($r->{tag} eq "meta") or ($r->{tag} eq "link")) {
        $etag = "";
      } else {
        $etag = "</".$r->{tag}.">"; 
      }
      $out .= $file.":0:".$stag;
      foreach (split(/\n/, $r->{attr})) { $out .= " ".$_ ; }
      $out .= ">";
      $out .= $r->{text} if $r->{text};
      $out .= $etag."\n";
    }
    return wantarray ? split("\n",$out) : $out;
}

sub ParseFile {
    use strict;
    require HTML::TokeParser;
    my $file = shift || return;
    my $Current = &newCurrent();
    my $Result = &newResult();
    my $p = HTML::TokeParser->new($file) || die "Can't open: $!";
    while (my $token = $p->get_token) {
    # ["S", $tag, %$attr, @$attrseq, $origtext]
      if    ($token->[0] eq "S") { &Handle_S($Current,$Result,$token); }
      elsif ($token->[0] eq "T") { &Handle_T($Current,$token->[1]); }
      elsif ($token->[0] eq "E") { &Handle_E($Current,$Result); }
    }
    return $Result;
}

sub newCurrent {
    use strict;
    my %current = (
        tag => undef,
        text => undef,
        seq => undef,
        attrs => undef
    );
    return \%current;
}

sub newResult {
    use strict;
    my @result = ();
    return \@result;
}

sub Handle_S {
    use strict;
    my $current = shift;
    my $result = shift;
    my $token = shift;
    my $type = $token->[0];
    my $tag = $token->[1];
    my %attr = %{$token->[2]};
    my @seq = @{$token->[3]};
    my $text = $token->[4];
    &SaveTagInfo($current,$result) if $current->{tag};
    $current->{tag} = $tag;
    foreach (@seq) {
     $current->{attrs}{$_} = $attr{$_};
    }
    @{$current->{seq}} = @seq;
}

sub Handle_T {
    use strict;
    my $current = shift;
    my($text) = @_;
    return unless $current->{tag};
    $text =~ s/\s+$//;
    $text =~ s/^\s+//;
    chomp $text;
    $current->{text} = $text;
}

sub Handle_E {
    use strict;
    my $current = shift;
    my $result = shift;
    &SaveTagInfo($current,$result) if $current->{tag};
    $current->{tag} = "";
}

sub SaveTagInfo {
    use strict;
    my $current = shift;
    my $result = shift;
    return unless $current->{tag};
    my %taginfo = ();
    my @attr = ();
    $taginfo{tag} = $current->{tag};
    $taginfo{text} = $current->{text};
    $taginfo{seq} = join(',',@{$current->{seq}});
    foreach (@{$current->{seq}}) {
      push(@attr, $_.'="'.$current->{attrs}{$_}.'"');
    }
    $taginfo{attr} = join("\n",@attr);

    push(@$result, \%taginfo);
}

