/*
....[@@@..[@@@..............[@.................. MUD++ is a written from
....[@..[@..[@..[@..[@..[@@@@@....[@......[@.... scratch multi-user swords and
....[@..[@..[@..[@..[@..[@..[@..[@@@@@..[@@@@@.. sorcery game written in C++.
....[@......[@..[@..[@..[@..[@....[@......[@.... This server is an ongoing
....[@......[@..[@@@@@..[@@@@@.................. development project.  All 
................................................ contributions are welcome. 
....Copyright(C).1995.Melvin.Smith.............. Enjoy. 
------------------------------------------------------------------------------
Melvin Smith (aka Fusion)         msmith@falcon.mercer.peachnet.edu 
MUD++ development mailing list    mudpp-list@spice.com
------------------------------------------------------------------------------
pc_olc.cc
*/

#include "string.h"
#include "llist.h"
#include "room.h"
#include "repop.h"
#include "indexable.h"
#include "server.h"
#include "repop.h"
#include "area.h"
#include "bit.h"
#include "edit.h"
#include "pc.h"

#include "global.h"

bool PC::checkSecurity()
{
	if( !in_room )
		return false;
	else if( security > in_room->getArea()->getSecurity() )
		return false;
	return true;
}


void PC::quitEditor()
{
	if( text )
	{
		if( editor )
		{

		}

		delete text;
		text = 0;
	}

	if( editor )
	{
		delete editor;
		editor = 0;
	}
	out( "Editor done.\n\r" );
}


void PC::editText( String str )
{
	text = new TextEditor( str );
	out( ((TextEditor *)text)->format() );
}


void PC::do_aedit( String & arg )
{
	if( !arg )
	{
		editor = new AreaEditor( this, in_room->getArea() );
		editor->command( "" );
		return;
	}
	else
	{
		if( arg == "create" || arg == "new" )
		{
			editor = new AreaEditor( this, new Area );
			out( "New area created.\n\r" );
			return;
		}
		else
		{
			Area *area = lookupArea( arg );
			if( !area )
			{
				out( "No such area.\n\r" );
				return;
			}

			if( area->getSecurity() < security )
			{
				out( "That area is out of your security range.\n\r" );
				return;
			}

			editor = new AreaEditor( this, area );
			editor->command( "" );
			return;
		}
	}
}


void PC::do_oedit( String & arg )
{
	if( !arg )
	{
		editor = new ObjectEditor( this, 0 );
		editor->command( "" );
		return;
	}

	Object *obj;

	if( !( obj = lookupObj( arg ) ) )
	{
		out( "No such object.\n\r" );
		return;
	}

	editor = new ObjectEditor( this, obj );
	editor->command( "" );
	return;
}


void PC::do_redit( String & arg )
{
	if( !arg )
	{
		editor = new RoomEditor( this, in_room );
		editor->command( "" );
		return;
	}

	Room *room;

	arg.startArgs();

	String arg1 = arg.getArg();
	String arg2 = arg.getArg();

	Index rIndex;
	Area *area;

	if( arg1 == "new" )
	{
		if( !arg2[0] )
		{
			out( "No index specified for new room.\n\r" );
			return;
		}
		else
		{
			rIndex = arg2;

			if( !rIndex.getKey()[0] )
			{
				out( "Room index must contain a key.\n\r" );
				return;
			}
			else if( rIndex.getScope()[0] )
			{
				if( !( area = lookupArea( rIndex.getScope() ) ) )
				{
					out( "Invalid area scope specified for new room.\n\r" );
					return;
				}
			}
			else
			{
				area = in_room->getArea();
			}

			if( ( room = area->lookupRoom( rIndex.getKey() ) ) )
			{
				out( "Error, a room already exists with that index.\n\r" );
				return;
			}

			room = new Room( area, rIndex.getKey() );
			area->addRoom( room );
			editor = new RoomEditor( this, room );
			editor->command( "" );
			return;
		}
	}

	// Not find a command so see if it is a room index
	rIndex = arg1;

	if( rIndex.getScope()[0] )
	{
		if( !( area = lookupArea( rIndex.getScope() ) ) )
		{
			out( "No such area " );
			out( rIndex.getScope() );
			out( "\n\r" );
			return;
		}
		else if( !( room = area->lookupRoom( rIndex ) ) )
		{
			out( "No such room " );
			out( rIndex.asString() );
			out( " in area " );
			out( rIndex.getScope() );
			out( "\n\r" );
			return;
		} 
	
		editor = new RoomEditor( this, room );
		editor->command( "" );
		return;	
	}
	else
	{
		if( !( room = in_room->getArea()->lookupRoom( rIndex ) ) )
		{
			out( "No such room in this area.\n\r" );
			return;
		} 

		editor = new RoomEditor( this, room );
		editor->command( "" );
		return;
	}	
}


void PC::do_mload( String & arg )
{
	Index x( arg );
	const NPC *prototype;

	// Check for scope, if not provide default scope
	// Default to the area we are standing in, if not
	// resolved then clear the area field and look for global


	if( !x.getScope()[0] )
	{
		x.setScope( in_room->getArea()->getKey() );

		prototype = lookupNPC( x );
		if( !prototype )
			x.setScope( "" );
	}

	prototype = lookupNPC( x );

	if( !prototype )
	{
		out( "No such mobile.\n\r" );
		return;
	}

	NPC *npc = new NPC( *prototype );

	npc->toWorld();

	// Add a hit attack to the npc's list.
	npc->addAttack();

	in_room->addCharInv( npc );
	String str;
	str << "Mobile '" << npc->getShort() << "' loaded.\n\r";
	out( str );
	str.clr();
	str << name << " has created " << npc->getShort() << "\n\r";
	in_room->outAllCharExcept( str, this, 0 );
}


void PC::do_oload( String & arg )
{
	Index x( arg );
	const Object * prototype;

	// Check for scope, if not provide default scope
	// Default to the area we are standing in, if not
	// resolved then clear the area field and look for global

	if( !x.getScope() )
	{
		x.setScope( in_room->getArea()->getKey() );

		prototype = lookupObj( x );
		if( !prototype )
			x.setScope( "" );
	}

	prototype = lookupObj( x );

	if( !prototype )
	{
		out( "No such object.\n\r" );
		return;
	}


	Object *obj = new Object( *prototype );

	obj->toWorld();
	in_room->addObjInv( obj );

	String str;
	str << "Object '" << obj->getShort() << "' loaded.\n\r";
	out( str );
	str.clr();
	str << name << " has created " << obj->getShort() << "\n\r";
	in_room->outAllCharExcept( str, this, 0 );
}


void PC::do_repops( String & arg )
{
	Repop *repop;
	String str;
	
	if( arg == "list" )
	{
		in_room->repops.reset();
		while( ( repop = in_room->repops.peek() ) )
		{
			str << repop->type << " " << repop->index.asString();
			if( repop->getPtr() )
				str << " -> " << repop->getPtr()->getShort();

			str << "\n\r";
			in_room->repops.next();
		}

		out( str );	
	}
	else if( arg == "room" )
	{
		in_room->repop();
		out( "Room reset.\n\r" );		
	}
	else if( arg == "area" )
	{
		in_room->getArea()->repop();
		out( "Area reset.\n\r" );
	}
	else if( arg == "world" )
	{
		LList<Area> tList = areas;
		Area *area;

		tList.reset();
		while( ( area = tList.peek() ) )
		{
			tList.next();
			area->repop();
		}
	}
	else
	{
		out( "Usage:    repop  { list | room | area | world }\n\r" );
		return;
	}
}