#!/usr/bin/perl
use Fcntl qw(:DEFAULT :flock);
#use Mooix::Thing;
use POSIX q{tmpnam};
run sub {
	my $this=shift;
	%_=@_;
	my $input=$_{input};
	my $hint=$_{hint} || "tmpfile";
	
	# Just in case.
	$hint=~y#/#_#;
	
	# Editing will be done using a real unix editor. Yes, they can run
	# inside the moo! Which editor is used depends on the editor
	# field/method of the avatar that is running this editing session.
	my $editor=$this->avatar->editor;

	# Users tend to customized editors a lot, and so it is helpful to
	# set HOME to point to the user who is editing so the editor sees
	# any config files. The user is the owner of the avatar.
	my $owner=(stat($this->avatar->id))[4];
	$ENV{HOME}=(getpwuid($owner))[7];
	
	# Set up a temp file for editing in /tmp, and write the input value
	# to it.
	my $tmpfile;
	do { $tmpfile = POSIX::tmpnam()."-$hint" }
	until sysopen(FH, $tmpfile, O_WRONLY|O_TRUNC|O_CREAT|O_EXCL, 0600);
	print FH $input."\n";
	close FH;
	
	open(TTY, "+<", $this->fieldfile("tty")) || $this->croak("open tty");
	
	# Have to fix up stdio to point to the tty so the editor works.
	open(OLDOUT, ">&STDOUT");
	open(STDOUT, '>&TTY');
	open(STDIN, '<&TTY');
	
	# Also, TERM needs to be set from the term field.
	$ENV{TERM}=$this->term;
	
	# Get an exclusive lock on the tty. This prevents messages from
	# interrupting the editing session.
	flock(TTY, LOCK_EX);
	
	my $ret=system($editor, $tmpfile);
	
	# Emacs is problimatic, since it refuses to reset the terminal on
	# exit unless the process group matches the foreground process group
	# of the controlling terminal. Problem is, it won't, and we can't
	# take over the terminal to make it. So, this is a nasty little
	# hack to reset the terminal after emacs exits.
	if ($editor =~ /emacs/i) {
		system("tset", "-I", "-Q");
		system("clear");
	}
	
	# Put back stdout so the return below works.
	open(STDOUT, '>&OLDOUT');
	
	if ($ret != 0) {
		$this->write("Your editor is misconfigured.");
		return;
	}
	
	my $contents;
	{
		open(FH, $tmpfile) || $this->croak("open $tmpfile");
		local $/=undef;
		$contents=<FH>;
	}
	unlink $tmpfile;
	
	return $this->avatar->edit_finish(session => $this, id => $_{id},
	                                  value => $contents);
}
