#!/usr/bin/perl
#use Mooix::Root;
#use Mooix::Thing;
#use Mooix::Verb;
use Mooix::Conf;

# Use Lingua::EN::Inflect if available, otherwise, do it ourselves.
eval "use Lingua::EN::Inflect qw(A AN)";
if ($@) {
	eval {
		sub A {	return "a".($_[0] =~ /^[aeiou]/i ? 'n' : '')." ".$_[0] }
		sub AN { A(@_) }
	}
}

sub splitnames {
	my $name=shift;
	return unless length $name;
	return map { s/^\s//; s/\s$//; $_ } split(',', $name);
}

run sub {
	my $this=shift;
	%_=@_;
	
	# Make sure that this command is not spoofed, just in case.
        if ($_{avatar} != $this) {
		fail "No!"; 
	}
	
	my @created_objs;
	my $session=$_{session};
	my $avatar=$_{avatar};
	# The verb can be called in three different ways. Either there is a
	# second quote, and exits are to be made, or there is just one
	# quote, the name of the room to make, or there is a direct object,
	# an existing room, and we just add exit(s).
	my ($roomname, $toname, $fromname, $room);
	if (exists $_{direct_object}) {
		$room = $_{direct_object};
		$roomname = $room->name;
		($toname, $fromname) = split(/\|/, $_{quote});
	}
	elsif (exists $_{quote2}) {
		($toname, $fromname) = split(/\|/, $_{quote});
		$roomname=$_{quote2};
	}
	else {
		$roomname=$_{quote};
	}

	my @tonames=splitnames($toname);
	$toname=shift @tonames;
	my @fromnames=splitnames($fromname);
	$fromname=shift @fromnames;
	
	# The parents for the room and exit to create. These are based on
	# the room the digging is done in, and on its exittype field, and
	# the exittype field of the destination room.
	my $roomparent;
	my $exitparent;
	# Find first room down that is not furniture.
	my $loc=$this->location;
	if (ref $loc) {
		my $furniture=$Mooix::Root->concrete->furniture;
		my $roomclass=$Mooix::Root->concrete->room;
		while (ref loc && (! $loc->isa($roomclass) || $loc->isa($furniture))) {
			$loc=$this->location;
		}
	}
	if (ref $loc) {
		# Room parent will be the parent of the room. Wow.
		$roomparent=$loc->parent;
		# But don't use distobjs for room parents. Ie, if digging
		# from the room entrance, go up to the real parent, don't
		# use the distobj room entrance.
		while (ref $roomparent && 
		       $roomparent->id =~ /^\Q$Mooix::Conf::field{distobj}\E/) {
			$roomparent=$roomparent->parent;
		}
		if (! ref $roomparent) {
			$roomparent=$Mooix::Root->concrete->room;
		}
		
		# Get the two types of exits.
		my $typea=$loc->exittype;
		if (! ref $typea) {
			$typea=$Mooix::Root->concrete->exit;
		}
		my $typeb;
		if ($room) {
			$typeb=$room->exittype
		}
		if (! ref $typeb) {
			$typeb=$Mooix::Root->concrete->exit;
		}
		
		# If one type is the ancestor of the other, use the other
		# as the exitparent. This makes doors get made properly if
		# made into a room that has an exittype of door, from a
		# room that has an exittype of exit, for example.
		if ($typea->isa($typeb)) {
			$exitparent=$typea;
		}
		elsif ($typeb->isa($typea)) {
			$exitparent=$typeb;
		}
		else {
			# Search for a common parent, and use it.
			my %seen;
			while (ref $typea) {
				$seen{$typea->index}=1;
				$typea=$typea->parent;
			}
			while (ref $typeb) {
				if ($seen{$typeb}) {
					$exitparent=$typeb;
					last;
				}
				$typeb=$typeb->parent;
			}

			if (! ref $exitparent) {
				# Should never happen..
				$exitparent=$Mooix::Root->concrete->exit;
			}
		}
	}
	else {
		# No location (or something strange); use defaults.
		$roomparent=$Mooix::Root->concrete->room;
		$exitparent=$Mooix::Root->concrete->exit;
	}
	
	# Make room.
	if (! $room) {
		my ($stat, $val, @rest) = $this->safechange(
			object => $this->portfolio."/".$roomname,
			newid => 1,
			field => "parent",
			value => $roomparent,
			
			object => "mooix:#1",
			field => "name",
			value => $roomname,
		);
		fail "Failed to create room." unless $stat;
		$room = $val;
		$room->init;
		$session->write("Created ".A($roomparent->name).
				" (".$this->refstring($room).").");
		push @created_objs, $room;
	}

	my ($fromexit, $toexit);
	
	# Make exit into the room, and put in avatar's location.
	if (length $toname) {
		my ($stat, $val, @rest) = $this->safechange(
			object => $this->portfolio."/".$toname,
			newid => 1,
			field => "parent",
			value => $exitparent,

			object => "mooix:#1",
			field => "name",
			value => $toname,

			object => "mooix:#1",
			field => "destination",
			value => $room,

			# Set aliases if there are any.
			( @tonames ? (
					object => "mooix:#1",
					field => "alias",
					( map { ( "value" => $_ ) } @tonames )
				     ) : ""
		  	),
		);
		fail "Failed to create exit." unless $stat;
		$toexit=$val;
		$toexit->init;
		
		if (! $toexit->physics->move(object => $toexit, to => $avatar->location, teleport => 1)) {
			$session->write("Failed to add an exit from here to ".$room->name." (contact ".$room->owner->name." to get that done).");
			$this->portfolio->remove(object => $toexit, quiet => 1);
			$toexit=undef;
		}
		else {
			$session->write("Added ".AN($exitparent->name)." ".
				"(".$this->refstring($toexit).") from here ".
				$toexit->name." to ".$room->prettyname.".");
			push @created_objs, $toexit;
		}
	}
		
	# Make exit from room, and put in room.
	if (length $fromname) {
		my ($stat, $val, @rest) = $this->safechange(
			object => $this->portfolio."/".$fromname,
			newid => 1,
			field => "parent",
			value => $exitparent,

			object => "mooix:#1",
			field => "name",
			value => $fromname,

			object => "mooix:#1",
			field => "destination",
			value => $avatar->location,

			# Set aliases if there are any.
			( @fromnames ? (
					object => "mooix:#1",
					field => "alias",
					( map { ( "value" => $_ ) } @fromnames )
				     ) : ""
		  	),
		);
		fail "Failed to create exit." unless $stat;
		$fromexit=$val;
		$fromexit->init;
		
		if (! $fromexit->physics->move(object => $fromexit, to => $room, teleport => 1)) {
			$session->write("Failed to add an exit from ".$room->name." to here.");
			$this->portfolio->remove(object => $fromexit);
			$fromexit=undef;
		}
		else {
			$session->write("Added ".AN($exitparent->name)." ".
				"(".$this->refstring($fromexit).") from ".
				$room->prettyname." ".$fromexit->name.
				" to here.");
			push @created_objs, $fromexit;
		}
	}

	if (ref $fromexit and ref $toexit) {
		$fromexit->otherside($toexit);
		$toexit->otherside($fromexit);
	}

	# Set "them" or "it" to the created objects.
	print join("\n", @created_objs)."\n";
	exit Mooix::Verb::SETITREF;
}
