package Common::SmartCat;

#
# SmartCat v2.10
# Copyright Benvolio mindcrimer <Benvolio@jerusalimov.ru> 1999-2001
#

use strict;
use warnings;

use Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw(
	smartcat
	smartcatRef
	smartcat2string
	file2string
	file2stringRef
	quote_str
	html_quote_str
	cutfixstr
);

# -- show parsing trace info --
our $parse_trace = 0;

# -- don't change anything below the line --


sub smartcat
{
	my ($hash,$templ) = @_;
	open(TEMPL,$templ) or return 0;
	while(<TEMPL>)
	{
		while(/<!--ins\[(.*?)]-->/)
		{
			my $key = $1;
			my $default_val = '';
			($key,$default_val) = ($1,$2) if ($key =~ /^([^=]+)=([^=]+)$/);
			my $val = $hash->{$key};
			$val = $default_val unless $val;
			s/<!--ins\[.*?]-->/$val/
		}  
		print $_
	}
	close(TEMPL);
	return 1
}

sub smartcatRef
{
	my ($hash,$templ) = @_;
	my $strtmp = '';
	my @TEMPL = split(/\r/,$$templ);
	foreach (@TEMPL)
	{
		while(/<!--ins\[(.*?)]-->/)
		{
			my $key = $1;
			my $default_val = '';
			($key,$default_val) = ($1,$2) if ($key =~ /^([^=]+)=([^=]+)$/);
			my $val = $hash->{$key};
			$val = $default_val unless $val;
			s/<!--ins\[.*?]-->/$val/
		} 
		$strtmp .= $_
	}
	$strtmp
}


sub smartcat2string
{
	my ($hash,$templ) = @_;
	my $str = '';
	open(TEMPL,$templ) or return '';
	while(<TEMPL>)
	{
		while(/<!--ins\[(.*?)]-->/)
		{
			my $key = $1;
			my $default_val = '';
			($key,$default_val) = ($1,$2) if ($key =~ /^([^=]+)=([^=]+)$/);
			my $val = $hash->{$key};
			$val = $default_val unless $val;
			s/<!--ins\[.*?]-->/$val/
		}  
		$str .= $_
	}
	close(TEMPL);
	$str
}

sub file2string
{
	my $templ = shift or return '';
	my $str = '';
	open(TEMPL,$templ) or return '';
	while(<TEMPL>) { $str .= $_ }
	close(TEMPL);
	$str
}

sub file2stringRef
{
	my $templ = shift or return 0;
	my $str;
	$$str = '';
	open(TEMPL,$templ) or return 0;
	while(<TEMPL>) { $$str .= $_ }
	close(TEMPL);
	return $str
}

sub quote_str
{
	my $str = shift or return '';
	$str =~ s/\"/\\"/g;
	return $str;
}

sub html_quote_str
{
	my $str = shift or return '';
	$str =~ s/\"/\&quot;/g;
	return $str;
}

sub cutfixstr
{
	my $str = shift or return '';
	my $cutmax = shift or return '';
	my $str_end = shift or return '';

	$str =~ s/\s+/ /g;

	return $str if(length($str)<=$cutmax);
	return substr(substr($str,0,rindex(substr($str,0,$cutmax),' ')).$str_end,0,$cutmax);
}

my %parse_cond = ('action'=>'','value'=>0,'ifdepth'=>0); # ifdepth - will be realized in next versions

sub parse_line
{
	my $BLOCK_ENV = shift;
	my $line = shift;
	my $parse_pattern = '<\!--(exec|set)\[([^]]+)\]-->';

	while($line =~ m/$parse_pattern/)
	{
		my ($action,$value) = ($1,$2);

		if($action eq 'exec')
		{
			my ($key,$val) = ($value =~ /(\w+)\((.*)\)/);
			print "#> exec: $key => $val" if ($parse_trace);
			if($key eq 'IFMATCH')
			{
				$parse_cond{'action'} = 'if';
				my ($part1,$part2) = split(/={1,2}/,$val);
				$BLOCK_ENV->{$part1} = $part1 if ($part1 =~ m/^\d+$/);
				$BLOCK_ENV->{$part2} = $part2 if ($part2 =~ m/^\d+$/);
				$parse_cond{'value'} = 1 if ($BLOCK_ENV->{$part1} eq $BLOCK_ENV->{$part2});
				print "; $part1=>\"$$BLOCK_ENV{$part1}\" & $part2=>\"$$BLOCK_ENV{$part2}\"" if ($parse_trace);
			}
			if($key eq 'ELSE')
			{
				if($parse_cond{'action'} eq 'if' && !$parse_cond{'value'})
				{
					$parse_cond{'action'} = 'else';
					$parse_cond{'value'} = 1;
				}
				else
				{
					$parse_cond{'action'} = 'else' ;
					$parse_cond{'value'} = 0;
				}
			}
			if ($key eq 'ENDIF')
			{
				$parse_cond{'action'} = '' ;
				$parse_cond{'value'} = 0;
			}
		}
		if($action eq 'set')
		{
			my ($key,$val) = split(/=>/,$value,2);
			print "#> set: $key => $val; cond. = $parse_cond{'action'} & $parse_cond{'value'}" if ($parse_trace);
			$BLOCK_ENV->{$key} = $val if (parse_rule());
		}
		$line =~ s/$parse_pattern//;
		print "; rule: ".parse_rule()."\n" if ($parse_trace);
	}
	return (parse_rule() ? smartcatRef($BLOCK_ENV,\$line) : '');
}

sub parse_env
{
	my $BLOCK_ENV = shift;
	my $line = shift;
	my $parse_pattern = '<\!--set\[([^]]+)\]-->';

	while($line =~ m/$parse_pattern/)
	{
		my ($key,$val) = split(/=>/,$1,2);
		print "#> set: $key => $val; cond. = $parse_cond{'action'} & $parse_cond{'value'}" if ($parse_trace);
		$BLOCK_ENV->{$key} = $val if (parse_rule());

		$line =~ s/$parse_pattern//;
		print "; rule: ".parse_rule()."\n" if ($parse_trace);
	}
	return 1;
}

sub parse_rule
{
	my $result = 0;
	$result = 1 if ( (!$parse_cond{'action'} && !$parse_cond{'value'}) or (($parse_cond{'action'} eq 'if' or $parse_cond{'action'} eq 'else') && $parse_cond{'value'}) );
	return $result;
}

sub parse_block
{
	my $BLOCK_ENV = shift;
	my $template = shift;

	my @block_parts = split(/(\r|\n)+/,$template);
	my $block_template = '';
	foreach (@block_parts)
	{
		$block_template .= parse_line($BLOCK_ENV,$_);
	}
	return $block_template;
}

sub parse_block_env
{
	my $BLOCK_ENV = shift;
	my $template = shift;

	my @block_parts = split(/(\r|\n)+/,$template);
	my $block_template = '';
	foreach (@block_parts)
	{
		$block_template .= parse_env($BLOCK_ENV,$_);
	}
	return 1;
}


1;
