package TDS::Replacer::Base;
# $Id: Base.pm,v 1.21 2001/01/10 08:12:45 tom Exp $
################################################################

=head1 NAME

TDS::Replacer::Base - 置換基本クラス

=head1 SYNOPSIS



=cut


################################################################

use strict qw(vars);
use Exporter;
use vars qw(@ISA @EXPORT
	    $EnableEscape $AdvancedReplacing);

@ISA = qw(ObjectTemplate);
@EXPORT = qw(attributes);

use ObjectTemplate;

use JConv;
use TDS::System;
use TDS::Collection;

=head1 STATIC VARIABLES

 $EnableEscape    エスケープによる置換抑制  

=cut

{
    $EnableEscape = 0 unless defined $EnableEscape;
    $AdvancedReplacing = 0 unless defined $AdvancedReplacing;
}

=head1 MEMBER VARIABLES

 datafile        データファイル名

=cut

attributes qw(datafile contents);

################################################################
=head1 MEMBER FUNCTIONS

=cut


sub initialize($)
{
    my $self = shift;
    $self->contents({}) unless $self->contents;
}

################################################################
# public

=head2 $b->Read;

データファイルを読み込む

=cut

sub Read($)
{
    my $self = shift;
    open(F, $self->datafile) || return;
    # die "can't open datafile " . $self->datafile;
    *jconv_tmp = mkjconv($TDS::Collection::TdfJcode, $TDS::System::InternalJcode);
    
    my @lines = <F>;
    close F;

#    while (<F>){
    for (@lines){
	next if (/^$/ || /^\#/);
	chomp;
	my $tmp = $_;
	jconv_tmp(\$tmp);
	$self->ReadLine($tmp);
    }
}

=head2 $b->ReplaceLine($text);

$$text に置換を施す。
$$text には対象文字列へのリファレンスを渡す。

=cut

sub ReplaceLine($\$)
{
    my ($self, $text) = @_;

    # ここらへん高速化しなきゃなぁ
#    my $regex;
   #jconv_t2i(\$text);
    my $code;

    for (sort {length($b) <=> length($a) } keys %{$self->contents}){
	next unless $_;
	my $term = $_;
	# 対象語が英数の場合は単語区切りをつける
#	$regex .= "|$term";
	my $b_term = $term;
	if ($term =~ /^[A-Za-z0-9_\-\s]+$/){
	    $b_term = "\\b$term\\b";
#	} else {
#	    next;
	}
#	$code .= qq(\$\$text =~ s!(\Q$term\E)!replace(\$self, \"$term\", \$1)!ges;); "
#	next;

	if ($EnableEscape){
	    $$text =~ s!([\\]?$b_term)!replace($self, $term, $1)!ges;
#	    $$text =~ s![\\]?$b_term!replace($self, $term, $0)!ges;	    
	} else {
#	    $$text =~ s!\G([\x00-\xff]*?)($b_term)!replace($self, $term, $2, $1)!ges;
	    $$text =~ s!($b_term)!replace($self, "$term", $1)!ges;
#	    $$text =~ s!$b_term!replace($self, "$term", $0)!ges;
	}
    }
    return $$text;
#    eval $code;
#    die $@ if $@;
#    print $regex;
#    eval "study \$regex; \$\$text =~ s!($regex)!replace(\$self, \$1, \$1)!ges";
}
################################################################
# protected:

=head2 $b->ReadLine($line);

$line を読み込み、処理する。

=cut

sub ReadLine ($$)
{
    my ($self, $line) = @_;
    my ($term, $replaced, $rest) = split(/\t+/, $line);
    $self->contents->{$term} = {replaced=>$replaced,
				rest=>$rest};
    ($term, $replaced, $rest);
}

sub RealReplace($$$)
{
    my ($self, $term, $object) = @_;

#    return $self->contents->{$term}->{replaced};
    return $self->ApplyTemplate($self->contents->{$term}->{replaced}, {});

}
sub ApplyTemplate($$$)
{
    my ($self, $template, $params) = @_;
    return $template
	unless $AdvancedReplacing;
    
    require Template;
    for (1..10){
	my $var = $_ + 1;
	$params->{$_} = $$var;
    }
    return Template::Expand($template, $params);
}
sub replace ($$$)
{
    my ($self, $term, $object) = @_;

    if ($EnableEscape && $object =~ /^\\(.*)$/){        # エスケープで非置換を明示
	return $1;
    } elsif ( # ($` !~ /\n$/o &&              # 直前が行頭じゃなくて
	     # $` =~ /[A-Za-z0-9]$/o) ||    # 英数文字
	     # $' =~ /^[A-Za-z0-9]/o ||
#	      0
	      $` =~ m!<[^>]*$! ||         # タグ内か
	      $` =~ m!<a [^>]*>[^<]*$!  # anchor の要素内だったら置換しない
#	      $before =~ m!<[^>]*$!o ||         # タグ内か
#	      $before =~ m!<a [^>]*>[^<]*$!o  # anchor の要素内だったら置換しない
	     
	     ){
#	print STDERR ",";
	return $object;
    } else {
#	print STDERR ".";
	return $self->RealReplace($term, $object);
    }
}
1;
