# FILE: fcn-indx.pl
# DESCRIPTION: Reindexing of board
#-------------------------------------------------------------------------------
# DISCUS COPYRIGHT NOTICE
#
# Discus is copyright (c) 2002 by DiscusWare, LLC, all rights reserved.
# The use of Discus is governed by the Discus License Agreement which is
# available from the Discus WWW site at:
#    http://www.discusware.com/discus/license
#
# Pursuant to the Discus License Agreement, this copyright notice may not be
# removed or altered in any way.
#-------------------------------------------------------------------------------

use strict;
use vars qw($GLOBAL_OPTIONS $PARAMS $DCONF);

###
### INDEXING_main
###
### Controls reindexing of your board
###

sub INDEXING_main {
	my ($arg) = @_;
	if ($arg->{position} eq "" || $arg->{position} eq "start") {
		dreq("fcn-regn");
		my $filelist = incremental( { topic => $arg->{topic}, operation => "build"} );
		my %f;
		foreach my $J (@{ $filelist->{data} }) {
			chomp $J;
			$f{$1} += 1 if $J =~ /\/(\d+)\.$DCONF->{ext}$/;
		}
		if (my @l = grep { $f{$_} > 1 } keys %f) {
			my $subst = {};
			$subst->{general}->{count} = scalar @l;
			my @w = map { { filename => $_ } } @l;
			$subst->{list} = \@w;
			$subst->{arg}->{menuaction} = $arg->{menuaction};
			$subst->{arg}->{username} = $arg->{username};
			$subst->{arg}->{tempfile} = $filelist->{tempfile};
			
			
			
			screen_out("indxerr", $subst);
		}		
		my $subst = {};
		$subst->{'gauge'}->{'refresh_url'} = "$PARAMS->{cgiurl}?menu=$arg->{menuaction}&action=dr_indexing&username=$arg->{username}&tempfile=$filelist->{tempfile}";
		$subst->{'gauge'}->{'operation'} = 1;
		$subst->{'gauge'}->{'description'} = 100;
		$subst->{'gauge'}->{'percent'} = 0;
		screen_out("gauge", $subst);
	}
	if ($arg->{position} eq "continue") {
		dreq("fcn-regn");
		my $tempfile = incremental({ operation => "read", tempfile => $arg->{tempfile} });
		my $timer = time;
		my $ctr = $arg->{counter};
		my $topic = 0;
		my $fileopen = 0;
		my @profile_changes = ();
		while (1) {
			my $file = shift(@{ $tempfile->{data} }) or last;
			my ($tn, $pn) = split(/\D/, $file);
			next if $tn == 0;
			if ($topic != 0 && $topic != $tn) {
				unshift(@{ $tempfile->{data} }, $file);
				last;
			}
			if ($arg->{menuaction} == 1 || $arg->{menuaction} == 2) {
				if ($topic == 0) {
					open (TMP, ">> $DCONF->{admin_dir}/msg_index/$tn-tree.TMP") || error_message("File Write Error", "Could not create temporary tree index file in 'msg_index' directory!");
					$topic = $tn;
					$fileopen = 1;
				}
				my ($pdata, $subs) = build_page_data($tn, $pn);
				my $pdta1 = shift(@{ $pdata });
				chomp $pdta1;
				if (scalar(@{ $subs })) {
					print TMP $pdta1, "\t", join(",", @{ $subs }), "\n";
				} else {
					print TMP $pdta1, "\tX\n";
				}
				if (scalar(@{ $pdata })) {
					print TMP @{ $pdata };
				}
			} elsif ($arg->{menuaction} == 3) {
				dreq("fcn-logs");
				if ($topic == 0) {
					open (TMP, ">> $DCONF->{admin_dir}/msg_index/$tn-search.TMP") || error_message("File Write Error", "Could not create temporary search index file in 'msg_index' directory!");
					$topic = $tn;
					$fileopen = 1;
				}
				my $messages = build_search_data($tn, $pn);
				foreach my $m (@{ $messages }) {
					print TMP search_hash_to_line($m);
				}
			}
			$ctr++;
			if ($ctr % 10 == 0) {
				last if time > ($timer+2+$GLOBAL_OPTIONS->{reindex_secs});
			}
		}
		close (TMP) if $fileopen;
		my $res = incremental({ operation => "write", data => $tempfile->{data}, tempfile => $arg->{tempfile} });
		my $subst = {};
		$subst->{'gauge'}->{'operation'} = 1;
		if ($res->{'continue'} == 1) {
			$subst->{'gauge'}->{'refresh_url'} = "$PARAMS->{cgiurl}?menu=$arg->{menuaction}&action=dr_indexing&username=$arg->{username}&tempfile=$arg->{tempfile}&counter=$ctr";
			$subst->{'gauge'}->{'description'} = 100;
			$subst->{'gauge'}->{'percent'} = int(100 * $ctr / ($ctr + scalar(@{ $tempfile->{data} }))) if ($ctr + scalar(@{ $tempfile->{data} })) > 0;
		} else {
			if ($arg->{menuaction} == 1 || $arg->{menuaction} == 2) {
				$subst->{'gauge'}->{'refresh_url'} = "$PARAMS->{cgiurl}?menu=$arg->{menuaction}&action=dr_sorting&username=$arg->{username}&counter=0";
				$subst->{'gauge'}->{'description'} = 101;
				$subst->{'gauge'}->{'percent'} = 0;
			} elsif ($arg->{menuaction} == 3) {
				$subst->{'gauge'}->{'refresh_url'} = "$PARAMS->{cgiurl}?action=dr_sindxfin&username=$arg->{username}&counter=0";
				$subst->{'gauge'}->{'description'} = 103;
				$subst->{'gauge'}->{'percent'} = 0;
			}
		}
		screen_out("gauge", $subst);
	}
	if ($arg->{position} eq "sort") {
		my $counter = $arg->{counter};
		my @dir = ();
		opendir(DIR, "$DCONF->{admin_dir}/msg_index");
		while (my $dir = readdir(DIR)) {
			if ($dir =~ m|^(\d+)-tree.TMP$|) {
				push(@dir, $1);
			}
		}
		closedir(DIR);
		if (my $x = shift(@dir)) {
			sorter($x);
			$counter += 1;
		} else {
			my $tpcs = board_topics();
			open (FILE, "> $DCONF->{admin_dir}/tree.txt");
			foreach my $y (@{ $tpcs }) {
				open (SUB, "< $DCONF->{admin_dir}/msg_index/$y->{number}-tree.txt");
				print FILE (<SUB>)[0];
				close (SUB);
			}
			close (FILE);
			dreq("topic-pg");
			regenerate_topic_page();
			return 1;
		}
		undef my $subst;
		$subst->{'gauge'}->{'operation'} = 1;
		$subst->{'gauge'}->{'refresh_url'} = "$PARAMS->{cgiurl}?menu=$arg->{menuaction}&action=dr_sorting&username=$arg->{username}&counter=$counter";
		$subst->{'gauge'}->{'description'} = 101;
		$subst->{'gauge'}->{'percent'} = int(100 * $counter / ($counter + scalar(@dir))) if ($counter + scalar(@dir)) > 0;
		screen_out("gauge", $subst);
	}
	if ($arg->{position} eq "search") {
		dreq("fcn-logs");
		my $counter = $arg->{counter};
		my @dir = @{ directory_list("$DCONF->{admin_dir}/msg_index", '^\d+-search\.TMP', 1) };
		if (my $x = shift(@dir)) {
			my $num = $1 if $x =~ /^(\d+)-/;
			if ($DCONF->{pro} && $GLOBAL_OPTIONS->{database}) {
				dreq("sql-imex-PRO", "dbint");
				my $dbh = db_connect();
				sql_dump_search_log_to_db("$DCONF->{admin_dir}/msg_index/$x", $dbh);
			} else {
				open (FILE, "< $DCONF->{admin_dir}/msg_index/$num-search.TMP");
				open (FILE2, "> $DCONF->{admin_dir}/msg_index/$num-search.txt");
				while (<FILE>) {
					print FILE2;
				}
				close (FILE);
				close (FILE2);
			}
			unlink "$DCONF->{admin_dir}/msg_index/$x";
			$counter += 1;
		} else {
			return 1;
		}
		undef my $subst;
		$subst->{'gauge'}->{'operation'} = 1;
		$subst->{'gauge'}->{'refresh_url'} = "$PARAMS->{cgiurl}?action=dr_sindxfin&username=$arg->{username}&counter=$counter";
		$subst->{'gauge'}->{'description'} = 103;
		$subst->{'gauge'}->{'percent'} = int(100 * $counter / ($counter + scalar(@dir))) if ($counter + scalar(@dir)) > 0;
		screen_out("gauge", $subst);
	}	
}

###
### sorter
###
### Provides sorting of entries in your tree file
###

sub sorter {
	my ($topic) = @_;
	undef my $tree;
	open (FILE, "$DCONF->{admin_dir}/msg_index/$topic-tree.TMP");
	while (<FILE>) {
		chomp $_;
		my @c = split(/\t/, $_);
		$tree->{subs}->{$c[2]} = pop @c;
		$tree->{data}->{$c[2]} = join("\t", @c);
	}
	close (FILE);
	my $res = (childfill($topic, $topic, $tree))[0];
	open (FILE, ">$DCONF->{admin_dir}/msg_index/$topic-tree.txt");
	print FILE @{$res};
	close (FILE);
	unlink("$DCONF->{admin_dir}/msg_index/$topic-tree.TMP");
	return 1;
}

###
### childfill
###
### Recursively fills in child page information
###

sub childfill {
	my ($topic, $page, $treeref) = @_;
	my @d = split(/\t/, $treeref->{data}->{$page});
	my @c = split(/,/, $treeref->{subs}->{$page});
	$treeref->{subs}->{$page} = undef;
	my @res = ();
	foreach my $subt (@c) {
		next if $subt eq "X";
		my ($cf, $posts, $subs, $lastmod, $lastposter) = childfill($topic, $subt, $treeref);
		$d[7] += $posts;
		$d[12] += $subs;
		if ($lastposter =~ /\S/) {
			$d[13] = $lastposter if $d[13] !~ /\S/;
			$d[13] = $lastposter if $lastmod > $d[9];
		}
		$d[9] = $lastmod if $lastmod > $d[9];
		next if ! defined $cf;
		push @res, @{ $cf };
	}
	unshift(@res, join("", join("\t", @d), "\n"));
	$treeref->{data}->{$page} = undef;
	return (\@res, $d[7], $d[12], $d[9], $d[13]);
}

###
### build_page_data
###
### Creates a tree entry for a page by reading the actual file
###

sub build_page_data {
	my ($topic, $page, $file) = @_;
	$file = GetPage($topic, $page) if ! defined $file;
	my @ret = ();
	my @m = map { $_->{number} } @{ $file->{messages} };
	my @stm = sort {$a->{'time'} <=> $b->{'time'}} @{ $file->{messages} };
	my $rr = {};
	$rr->{level} = (scalar(@{ $file->{head}->{levels} }) - 1);
	$rr->{level} = 0 if $rr->{level} < 0;
	$rr->{topic} = $topic;
	$rr->{page} = $page;
	$rr->{parent} = ( $topic == $page ? 0 : $file->{head}->{parent} );
	$rr->{name} = $file->{head}->{me_name};
	$rr->{param} = $file->{head}->{param};
	$rr->{posts} = scalar(@{ $file->{messages} });
	$rr->{properties} = $file->{head}->{properties};
	$rr->{lastmod} = 0;
	$rr->{lastmod} = $stm[ $#stm ]->{'time'} if $#stm >= 0;
	$rr->{post_list} = join(",", @m);
	$rr->{subs} = 1;
	if (scalar(@stm)) {
		for (my $i = $#stm; $i >= 0; $i--) {
			my $lp = $stm[$i]->{author};
			$lp = $` if $lp =~ /(?:\(|&#40;)(.*?)(?:\)|&#41;)/;
			if ($lp =~ /\S/) {
				$rr->{last_poster} = trim($lp);
				last;
			}
		}
		my $org = $stm[0]->{'author'};
		$org = $` if $org =~ /(?:\(|&#40;)(.*?)(?:\)|&#41;)/;
		$rr->{originator} = trim($org);
	}
	my @s = ();
	foreach my $s (@{ $file->{sublist} }) {
		push (@s, $s->{number});
		if ($s->{islink} == 1) {
			my $sl = {};
			$sl->{level} = $rr->{level} + 1;
			$sl->{topic} = $topic;
			$sl->{page} = $s->{number};
			$sl->{parent} = $page;
			$sl->{name} = $s->{name};
			$sl->{islink} = 1;
			$sl->{target} = $s->{target};
			$sl->{url} = $s->{url};
			$sl->{properties} = $s->{props};
			$sl->{subs} = 0;
			$sl->{lastmod} = 0;
			$rr->{subs} += 1;
			my $k = (generate_tree_line($sl))[0];
			chomp $k;
			$k .= "\tX\n";
			push @ret, $k;
		}
	}
	unshift @ret, (generate_tree_line($rr))[0];
	return (\@ret, \@s);
}

###
### build_search_data
###
### Creates a search entry for a page by reading the actual file
###

sub build_search_data {
	my ($topic, $page, $file) = @_;
	$file = GetPage($topic, $page) if ! defined $file;
	my @u = ();
	foreach my $l (@{ $file->{messages} }) {
		undef my $j;
		$j->{topic} = $topic;
		$j->{page} = $page;
		$j->{postindex} = $l->{number};
		$j->{'time'} = $l->{'time'};
		($j->{text}) = search_stop($l->{text}, undef);
		push @u, $j;
	}
	return \@u;
}
1;
