# FILE: fcn-pgmv.pl
# DESCRIPTION: Move an entire page from one place to another
#-------------------------------------------------------------------------------
# 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 $DCONF $PARAMS);

###
### move_page
###
### Moves a page from one place to another
###

sub move_page {
	my ($arg, $old_topic_tree, $new_topic_tree, $file_in, $user, $new_file_in) = @_;
	return undef if $arg->{new_page} == $arg->{page} && $arg->{new_topic} == $arg->{topic} && $arg->{new_conversation} == 0;
	dreq("fcn-tree");
	my $OLDTREE = defined $old_topic_tree ? $old_topic_tree : read_tree($arg->{topic}, { no_unlock => 1 });
	my @mv = keys(%{$arg->{move}});
	my $mv_c = {};
	my $q_c = tree_categorize($OLDTREE);
	foreach my $l (@mv) {
		if ($l == $arg->{new_page}) {
			unlock("$DCONF->{admin_dir}/msg_index/$arg->{topic}-tree.txt");
			error_message("Illegal Destination", "You cannot move pages onto themselves.", 0, 1) if ! $arg->{archive_action};
			return undef;
		}
		my $j = tree_build_children_of($OLDTREE, $q_c, $l);
		my @j = @{$j}; @j = tree_flatten(@j);
		foreach my $child (@j) {
			if ($child->{page} == $arg->{new_page}) {
				unlock("$DCONF->{admin_dir}/msg_index/$arg->{topic}-tree.txt");
				error_message("Illegal Destination", "You cannot move pages onto their children.", 0, 1) if ! $arg->{archive_action};
				return undef;
			}
		}
	}	
	my $NEWTREE = $arg->{topic} == $arg->{new_topic} ? $OLDTREE : (defined $new_topic_tree ? $new_topic_tree : read_tree($arg->{new_topic}, { no_unlock => 1 }));
	my $OLDFILE = defined $file_in ? $file_in : GetPage($arg->{topic}, $arg->{page}, { lock => 1 });
	my $NEWFILE = undef;
	my @m1 = (); my @m2 = ();
	foreach my $subt (@{ $OLDFILE->{sublist} }) {
		next if $subt->{number} == 0;
		if ($arg->{move}->{$subt->{number}}) {
			push @m2, $subt;
		} else {
			push @m1, $subt;
		}
	}
	if (scalar(@m2) == 0) {
		unlock("$DCONF->{message_dir}/$arg->{topic}/$arg->{page}.$DCONF->{ext}");
		unlock("$DCONF->{admin_dir}/msg_index/$arg->{topic}-tree.txt") if ! defined $old_topic_tree;
		unlock("$DCONF->{admin_dir}/msg_index/$arg->{new_topic}-tree.txt") if ! defined $new_topic_tree;;
		return (undef, $OLDTREE, $NEWTREE);
	}
	@m2 = grep($_->{number} > 0, @m2);
	@m1 = grep($_->{number} > 0, @m1);
	$OLDFILE->{sublist} = \@m1;
	if ($arg->{new_conversation} == 1) {
		dreq("fcn-pgad");
		my $narg = {};
		$narg->{topic} = $arg->{new_topic} == 0 ? $arg->{topic} : $arg->{new_topic};
		$narg->{host} = $arg->{new_page} == 0 ? $arg->{page} : $arg->{new_page};
		$narg->{type} = defined $arg->{type} ? $arg->{type} : 0;
		$narg->{name} = $arg->{create_new_page_name};
		$narg->{lastmod} = 1;
		$narg->{nosetpage} = 1;
		$narg->{tree_ref} = $NEWTREE;
		$file_in = $OLDFILE if $arg->{new_page} == $arg->{page};
		$narg->{pagehash} = $file_in if defined $file_in;
		$narg->{pagehash} = $OLDFILE if $OLDFILE->{head}->{me_number} == $arg->{page};
		my $ap = add_page($narg);
		$NEWFILE = $ap->{newfile};
		$arg->{new_page} = $ap->{number};
		if (defined $file_in && $arg->{new_page} != $arg->{page}) {
			SetPage($ap->{pghash}, { unlock => 1 });
		}
		$OLDFILE = $ap->{pghash} if $arg->{new_page} == $arg->{page};
		$NEWTREE = $ap->{tree};
		$OLDTREE = $ap->{tree} if $arg->{new_topic} == $arg->{topic};
		$NEWFILE->{sublist} = \@m2;
	} else {
		$NEWFILE = defined $new_file_in ? $new_file_in : GetPage($arg->{new_topic}, $arg->{new_page}, { lock => 1 });
		push @{ $NEWFILE->{sublist} }, @m2;
	}
	my ($tf, $ca, $pg, $Y) = tree_remove_page($OLDTREE, undef, join(",", keys(%{ $arg->{move} })), $arg->{old_page});
	my @y = @{ $Y };
	$OLDTREE = $tf;
	$NEWTREE = $tf if $arg->{topic} == $arg->{new_topic};
	my $newca = tree_categorize($NEWTREE);
	my $newpagetree = $NEWTREE->[ $newca->{array_pos}->{$arg->{new_page}} ];
	my $baselevel = $y[0]->{level};
	my $posts = 0; my $subs = 0; my $lastmod = ""; my $lastpost = "";
	my @mp = ();
	foreach my $thing (@y) {
		$posts += scalar(split(/,/, $thing->{post_list}));
		push @mp, split(/,/, $thing->{post_list});
		$subs += 1;
		if ($thing->{lastmod} > $lastmod) {
			$lastmod = $thing->{lastmod};
			$lastpost = $thing->{last_poster};
		}
		$thing->{topic} = $arg->{new_topic};
		$thing->{parent} = $arg->{new_page} if $thing->{parent} == $arg->{page};
		$thing->{level} = $newpagetree->{level} + $thing->{level} - $baselevel + 1;
		if ($arg->{archive_action}) {
			$thing->{param} =~ s/Add//g if $GLOBAL_OPTIONS->{autoarchive_msgadd} == 0;
			$thing->{param} =~ s/Create//g;
			$thing->{param} .= "Archive" if $thing->{param} !~ /Archive/;
		}
	}
	($tf, $ca) = tree_upward_update($tf, $ca, $arg->{page}, { metoo => 1, posts => "-$posts", subs => "-$subs" });
	$OLDTREE = $tf;
	$NEWTREE = $tf if $arg->{topic} == $arg->{new_topic};
	my ($tf2, $ca2) = tree_insert_record($NEWTREE, $newca, \@y);
	($tf2, $ca2) = tree_upward_update($tf2, $ca2, $arg->{new_page}, { metoo => 1, safe => 1, lastmod => $lastmod, last_poster => $lastpost, posts => "+$posts", subs => "+$subs" });
	$tf2->[ $ca2->{array_pos}->{$arg->{new_page}} ]->{param} .= "Sublist" if $newpagetree->{param} !~ /Sublist/;
	$NEWTREE = $tf2;
	$OLDTREE = $arg->{topic} == $arg->{new_topic} ? $tf2 : $tf;
	$OLDFILE->{sublist} = expand_sublist($OLDFILE->{sublist}, $arg->{topic}, $OLDTREE);
	$NEWFILE->{sublist} = expand_sublist($NEWFILE->{sublist}, $arg->{new_topic}, $NEWTREE);
	@{ $NEWFILE->{sublist} } = sort sort_archive_method @{ $NEWFILE->{sublist} } if $GLOBAL_OPTIONS->{sort_archive_method_on};
	@{ $OLDFILE->{sublist} } = sort sort_archive_method @{ $OLDFILE->{sublist} } if $GLOBAL_OPTIONS->{sort_archive_method_on};
	$OLDFILE->{general}->{subtopic_raw} = 0;
	$NEWFILE->{general}->{subtopic_raw} = 0;
	$NEWFILE->{head}->{param} .= "Sublist" if $NEWFILE->{head}->{param} !~ /Sublist/;
	SetPage($OLDFILE, { unlock => 1 }) if ! $arg->{no_write_files};
	SetPage($NEWFILE, { unlock => 1 }) if ! $arg->{no_write_files};
	write_tree($arg->{new_topic}, $NEWTREE, { no_lock => 1 }) if ! defined $new_topic_tree;
	if (! defined $new_topic_tree) {
		my $main_tree = readfile("$DCONF->{admin_dir}/tree.txt", "move_page", { no_unlock => 1 });
		$main_tree = topic_tree_to_main($NEWTREE, $main_tree, { no_write => 1 });
		$main_tree = topic_tree_to_main($OLDTREE, $main_tree, { no_write => 1 });
		writefile("$DCONF->{admin_dir}/tree.txt", $main_tree, "move_page", { no_lock => 1 });
	}
	if ($arg->{topic} == $arg->{new_topic}) {
		pages_upward_update($NEWTREE, $ca2, [ $arg->{page}, $arg->{new_page} ]) if ! $arg->{man_archive_action};
	} else {
		write_tree($arg->{topic}, $OLDTREE, { no_lock => 1 }) if ! defined $old_topic_tree;
		pages_upward_update($NEWTREE, $ca2, [ $arg->{new_page} ]) if ! $arg->{man_archive_action};
		pages_upward_update($OLDTREE, $ca, [ $arg->{page} ]) if ! $arg->{man_archive_action};
	}		
	my $moved_count = scalar(keys(%{ $arg->{move} }));
	my $pages_count = scalar(@y);
	if ($moved_count == $pages_count && $arg->{topic} == $arg->{new_topic} && scalar(@y) < 5) {
		foreach my $page (@m2) {
			next if $page->{type} != 0;
			next if $page->{islink};
			next if $page->{number} == 0;
			my $p = {};
			$p->{lock} = 1 if $arg->{man_archive_action} == 0;
			my $i = GetPage($arg->{topic}, $page->{number}, $p);
			$i->{head}->{parent} = $arg->{new_page};
			$i->{head}->{levels} = $NEWFILE->{head}->{levels};
			if ($arg->{archive_action}) {
				$i->{head}->{param} =~ s/Add//g if $GLOBAL_OPTIONS->{autoarchive_msgadd} == 0;
				$i->{head}->{param} =~ s/Create//g;
				$i->{head}->{param} .= "Archive" if $i->{head}->{param} !~ /Archive/;
			}
			push @{$i->{head}->{levels}}, { level_name => $i->{me_name}, level_number => $i->{me_number} };
			$i->{sublist} = expand_sublist($i->{sublist}, $arg->{topic}, $NEWTREE);
			SetPage($i, { unlock => 1 });	
		}
		return ($NEWFILE, $NEWTREE, $OLDFILE, $OLDTREE);
	} elsif ($arg->{archive_action} || ($arg->{topic} == $arg->{new_topic} && scalar(@y) < 5)) {
		foreach my $page (@y) {
			next if $page->{type} != 0;
			next if $page->{islink};
			next if $page->{page} == 0;
			my $p = {};
			$p->{lock} = 1 if $arg->{man_archive_action} == 0;
			my $i = GetPage($arg->{topic}, $page->{page}, $p);
			if ($i->{head}->{parent} == $arg->{page}) {
				$i->{head}->{parent} = $arg->{new_page};
				$i->{head}->{levels} = $NEWFILE->{head}->{levels};
			} else {
				my @l = ();
W:				while (my $l = pop @{ $i->{head}->{levels} }) {
					last W if $l->{level_number} == $arg->{page};
					unshift @l, $l;
				}
				unshift @l, @{ $NEWFILE->{head}->{levels} };
				$i->{head}->{levels} = \@l;
			}
			push @{$i->{head}->{levels}}, { level_name => $i->{me_name}, level_number => $i->{me_number} };
			if ($arg->{archive_action}) {
				$i->{head}->{param} =~ s/Add//g if $GLOBAL_OPTIONS->{autoarchive_msgadd} == 0;
				$i->{head}->{param} =~ s/Create//g;
				$i->{head}->{param} .= "Archive" if $i->{head}->{param} !~ /Archive/;
			}
			if ($arg->{topic} != $arg->{new_topic}) {
				$i->{head}->{topic_number} = $arg->{new_topic};
				$i->{head}->{topic_name} = $NEWFILE->{head}->{topic_name};
				my $new_topic = $arg->{new_topic};
				my $att = attachment_scan($i->{messages});
				my $sdir = get_message_path($arg->{topic});
				if (ref $att eq 'ARRAY' && scalar(@{$att})) {
					my $ddir = get_message_path($arg->{new_topic});
					foreach my $Z (@{$att}) {
						$i->{messages}->[$Z->{counter}]->{text} =~ s%/$arg->{topic}/$Z->{filename}%/$arg->{new_topic}/$Z->{filename}%gi;
						writefile_binary("$ddir/$Z->{filename}", readfile_binary("$sdir/$Z->{filename}")) && unlink "$sdir/$Z->{filename}";
					}
				}
				unlink "$sdir/$i->{head}->{me_number}.$DCONF->{ext}";
			}
			$i->{sublist} = expand_sublist($i->{sublist}, $arg->{new_topic}, $NEWTREE);
			$i->{general}->{subtopic_raw} = 0;		
			$i->{general}->{messages_raw} = 0;		
			SetPage($i, { unlock => 1 });	
		}
		return ($NEWFILE, $NEWTREE, $OLDFILE, $OLDTREE);
	} else {
		dreq("fcn-regn");
		my @m = ();
		my $inc = incremental_descendants($arg->{topic}, $arg->{page}, "MP", $NEWTREE, undef, \@m, $Y);
		my @arg = ();
		push @arg, join(",", keys(%{$arg->{move}}));
		push @arg, $arg->{topic};
		push @arg, $NEWFILE->{head}->{topic_number};
		push @arg, $NEWFILE->{head}->{topic_name};
		foreach my $J (@{ $NEWFILE->{head}->{levels} }) {
			push @arg, $J->{level_number};
			push @arg, $J->{level_name};
		}
		my $chgfile = regeneration_create_change_process_file("regen_move_page_functions", @arg);
		regenerate_board({ esc => 1, hold => regeneration_create_hold({ HTTP_REFERER => "/$arg->{topic}/$arg->{page}" }), topic => $arg->{topic}, tempfile => $inc->{tempfile}, done => 0, total => $inc->{count}, action => "regen4", username => $user, changefile => $chgfile, operation => 6, description => 601 }, undef, 1);
		return ($NEWFILE, $NEWTREE, $OLDFILE, $OLDTREE);
	}
}

1;
