# FILE: fcn-msmv.pl
# DESCRIPTION: Message Management (Move Message)
#-------------------------------------------------------------------------------
# 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_message
###
### Moves one or more messages from one page to another
###

sub move_message {
	my ($arg, $file_in, $old_topic_tree, $new_topic_tree) = @_;
	return undef if $arg->{new_page} == $arg->{page} && $arg->{new_topic} == $arg->{topic};
	my $old_file = defined $file_in ? $file_in : GetPage($arg->{topic}, $arg->{page}, { lock => 1 });
	my $old_tree_cache = defined $old_topic_tree ? $old_topic_tree : read_tree($arg->{topic}, { lock => 1 });
	my $new_tree_cache = $arg->{topic} == $arg->{new_topic} ? $old_tree_cache : (defined $new_topic_tree ? $new_topic_tree : read_tree($arg->{new_topic}, { lock => 1 }));
	my $new_file = undef;

	# Moves the messages themselves from old page to new page

	my @_ag = (); my @m1 = (); my @m2 = (); my @p = (); my @m2L = ();
	my %u = map { $_, 1 } split(/,/, $arg->{messages});
	foreach my $l (@{ $old_file->{messages} }) {
		if ($u{$l->{number}} == 1) {
			if ($arg->{topic} != $arg->{new_topic}) {
				my $att = attachment_scan($l->{text});
				foreach my $Z (@{$att}) {
					$l->{text} =~ s%/$arg->{topic}/$Z->{filename}%/$arg->{new_topic}/$Z->{filename}%gi;
					push @_ag, $Z->{filename};
				}
			}
			push @m2, $l;
			push @m2L, $l->{number};
			push @p, { postindex => $l->{number}, time => $l->{'time'}, old_topic => $arg->{topic}, old_page => $arg->{page}, new_topic => $arg->{new_topic}, new_page => $arg->{new_page} };
		} else {
			push (@m1, $l);
		}
	}
	if ($arg->{create_new_page}) {
		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->{type} = 4 if $arg->{archive};
		$narg->{name} = $arg->{create_new_page_name};
		$narg->{pagehash} = $old_file;
		$narg->{messages} = \@m2;
		$narg->{post_list} = join(",", @m2L);
		my @X = sort { $b->{'time'} <=> $a->{'time'} } @m2;
		$narg->{lastmod} = $X[0]->{'time'};
		$narg->{last_poster} = $X[0]->{'author'};
		$narg->{originator} = $X[$#X]->{'author'} if $#X >= 0;
		$narg->{tree_ref} = $new_tree_cache if defined $new_tree_cache;
		$narg->{msg_count} = scalar(@m2);
		if ($arg->{force_new_page_number}) {
			$narg->{force_new_page_number} = $arg->{force_new_page_number};
		}
		my $ap = add_page($narg);
		$old_file = $ap->{pghash};
		$new_file = $ap->{newfile};
		$arg->{new_page} = $ap->{number};
		$arg->{new_topic} = $narg->{topic};
		$old_file->{general}->{sublist_raw} = 0;
		$new_tree_cache = $ap->{tree};
		$old_tree_cache = $ap->{tree} if $arg->{new_topic} == $arg->{topic};
		foreach my $p (@p) {
			$p->{new_page} = $ap->{number};
		}
	} else {
		$new_file = GetPage($arg->{new_topic}, $arg->{new_page}, { lock => 1 });
		$new_file->{head}->{param} .= "Messages" if $new_file->{head}->{param} !~ /Messages/;
		if ($arg->{archive}) {
			$new_file->{head}->{param} .= "Archive" if $new_file->{head}->{param} !~ /Archive/;
			$new_file->{head}->{param} =~ s/Add//g;
		}		
		push @{ $new_file->{messages} }, @m2;
		$new_file->{general}->{messages_raw} = 0;
		SetPage($new_file, { unlock => 1 });
	}
	$old_file->{general}->{messages_raw} = 0;
	$old_file->{messages} = \@m1;
	SetPage($old_file, { unlock => 1 }) if ! defined $arg->{play_oldfile};
	
	# Update posting and search logs, if necessary

	dreq("fcn-logs");
	update_entry_post_location(\@p) if $arg->{topic} != $arg->{new_topic};
	
	# Move attachments to new directory, if needed
	
	if ($arg->{topic} != $arg->{new_topic} && scalar(@_ag)) {
		my $srcdir = -e "$DCONF->{message_dir}/$arg->{topic}" ? "$DCONF->{message_dir}/$arg->{topic}" : "$DCONF->{secdir}/$arg->{topic}";
		my $destdir = -e "$DCONF->{message_dir}/$arg->{new_topic}" ? "$DCONF->{message_dir}/$arg->{new_topic}" : "$DCONF->{secdir}/$arg->{new_topic}";
		foreach my $file (@_ag) {
			writefile_binary("$destdir/$file", readfile_binary("$srcdir/$file")) && unlink "$srcdir/$file";
		}
	}
	
	# Update the tree files and message counts on affected pages

	dreq("fcn-tree");
	my $uh1 = {};
	my $uh2 = {};
	my @j1 = (); my @j2 = ();
	foreach my $j (@m1) { push @j1, $j->{number}; }
	foreach my $j (@{ $new_file->{messages} }) { push @j2, $j->{number}; }
	$uh1 = { page => $arg->{page}, post_list => join(",", @j1) };
	$uh2 = { page => $arg->{new_page}, post_list => join(",", @j2) };
	my $moved = scalar(@m2);
	if ($arg->{new_topic} == $arg->{topic}) {
		my $treeX = defined $old_tree_cache ? $old_tree_cache : read_tree($arg->{topic}, { no_unlock => 1 });
		$treeX = tree_record_update($treeX, undef, $uh1, 1);
		$treeX = tree_record_update($treeX->{tree}, $treeX->{cat}, $uh2, 1);
		if (! $arg->{create_new_page}) {
			($treeX->{tree}, $treeX->{cat}) = tree_upward_update($treeX->{tree}, $treeX->{cat}, $arg->{page}, { metoo => 1, posts => "-$moved" });
			($treeX->{tree}, $treeX->{cat}) = tree_upward_update($treeX->{tree}, $treeX->{cat}, $arg->{new_page}, { metoo => 1, posts => "+$moved" });
		} else {
			($treeX->{tree}, $treeX->{cat}) = tree_upward_update($treeX->{tree}, $treeX->{cat}, $arg->{new_page}, { metoo => 0, pages => "+1" });
		}
		if (! defined $old_topic_tree || ! defined $arg->{play_oldtree}) {
			write_tree($arg->{topic}, $treeX->{tree}, { no_lock => 1 });
		}
		if ($arg->{pages_upward_update}) {
			pages_upward_update($treeX->{tree}, $treeX->{cat}, [ $arg->{page}, $arg->{new_page} ]);
		}	
		return {
			old_topic_tree => $treeX->{tree},
			new_topic_tree => $treeX->{tree},
			moved => $moved,
			arg => $arg,
			oldfile => $old_file,
			newfile => $new_file,
			cat => $treeX->{cat},
		};
	} else {
		my $treeX = defined $old_tree_cache ? $old_tree_cache : read_tree($arg->{topic}, { no_unlock => 1 });
		my $treeY = defined $new_tree_cache ? $new_tree_cache : read_tree($arg->{new_topic}, { no_unlock => 1 });
		$treeX = tree_record_update($treeX, undef, $uh1, 1);
		$treeY = tree_record_update($treeY, undef, $uh2, 1);
		if (! $arg->{create_new_page}) {
			($treeX->{tree}, $treeX->{cat}) = tree_upward_update($treeX->{tree}, $treeX->{cat}, $arg->{page}, { metoo => 1, posts => "-$moved" });
			($treeY->{tree}, $treeY->{cat}) = tree_upward_update($treeY->{tree}, $treeY->{cat}, $arg->{new_page}, { metoo => 1, posts => "+$moved" });
		} else {
			($treeY->{tree}, $treeY->{cat}) = tree_upward_update($treeY->{tree}, $treeY->{cat}, $arg->{new_page}, { metoo => 0, pages => "+1" });
		}			
		if (! defined $old_topic_tree || ! defined $arg->{play_oldtree}) {
			write_tree($arg->{topic}, $treeX->{tree}, { no_lock => 1 });
		}
		if (! defined $new_topic_tree || ! defined $arg->{play_newtree}) {
			write_tree($arg->{new_topic}, $treeY->{tree}, { no_lock => 1 });
		}
		if ($arg->{pages_upward_update}) {
			pages_upward_update($treeX->{tree}, $treeX->{cat}, [ $arg->{page} ]);
			pages_upward_update($treeY->{tree}, $treeY->{cat}, [ $arg->{new_page} ]);
		}	
		return {
			old_topic_tree => $treeX->{tree},
			new_topic_tree => $treeY->{tree},
			moved => $moved,
			arg => $arg,
			oldfile => $old_file,
			newfile => $new_file,
		};
	}
}


1;
