// Help.cpp - help code and related
// By: Odis

#include "help.h"
#include "stringutil.h"
#include "world.h"
#include "timestamp.h"
#include "log.h"
#include "split.h"
#include "avatar.h"
#include "commandTable.h"

//constructor
Help::Help(const string &n)
{
  Set("name", n);

  // load contents from DB
  Load(n);
}

// destructor
Help::~Help()
{
  HelpMap::iterator j = World::Instance()._help_map.find(Get("name"));

  if ( j != World::Instance()._help_map.end() )
   World::Instance()._help_map.erase(j);
}

bool Help::Set( const string &set, const string &value )
{
   info[set] = value;
   return true;
}

string Help::Get( const string &get )
{
	return info[get];
}

bool Help::Save()
{
	string query;

	// We have to escape certain strings because they may possibly have a single quote in them.
	query << "UPDATE help SET text='" << Mysql::Instance().EscapeString( Get( "text" ) ) <<
	"', author='" << Mysql::Instance().EscapeString( Get("author") ) <<
    "', permission='" << Mysql::Instance().EscapeString( Get("perm") ) <<
    "', last_update='" << Mysql::Instance().EscapeString( Get("last_update") ) <<
    "' WHERE name='" << Get("name") << "'";

    Mysql::Instance().RealQuery( query.c_str() );
    return true;
}

// load a help file
bool Help::Load(const string &n)
{
	string query;
	string exits;
	Mysql::LMAP::iterator help_info;
	Mysql::RESULT z;

	query << "SELECT * FROM help WHERE name='" << n << "'";

	if ( !Mysql::Instance().Load( query.c_str() ) )
		return false;

   z = Mysql::Instance()._info;


   help_info = z[0].find("text");
   Set( "text", help_info->second );

   help_info = z[0].find("id");
   Set( "id", help_info->second );

   help_info = z[0].find("last_update");
   Set( "last_update", help_info->second );
   
   help_info = z[0].find("creation_date");
   Set( "creation_date", help_info->second );

   help_info = z[0].find("author");
   Set( "author", help_info->second );

   help_info = z[0].find("permission");
   Set( "perm", help_info->second );

   // add it!
   World::Instance()._help_map[n] = this;

   return true;
}

// help edit handler stuffs
EditHelpHandler::EditHelpHandler()
{
	_edit = NULL;
	new_file = false;
}

EditHelpHandler::EditHelpHandler( Avatar * avatar, const string &name )
{
	string buf;

	if ( (_edit = World::Instance().FindHelp(name)) == NULL )
    {
        avatar->Send("\n\rCreating new help file...\n\r");
        string time = Timestamp::Instance().GetDateTime();
        
  	    buf << "INSERT INTO help ( name, author, last_update, creation_date ) VALUES ( '"
        << Mysql::Instance().EscapeString(name) << "', '" << Mysql::Instance().EscapeString(avatar->Get("name")) << "', '"
        << Mysql::Instance().EscapeString(time) << "', '" << Mysql::Instance().EscapeString(time) << "' )";

        if ( !Mysql::Instance().Query( buf.c_str() ) )
            glog( "EditHelpHandler::EditHelpHandler -> Failed Query!" );
        else
        {
         _edit = new Help(name);
         new_file = true;
        }
    }
    else if ( avatar->Get("group").find( _edit->Get("perm") ) == string::npos)
     avatar->ExitHandler(); // exit the handler, tried to edit without being of adaquete permissions


    _name = name;
	buf = "";
    buf << "You are now editing [{b" << name << "{x]\n\r";
	avatar->Send( buf );
}

void EditHelpHandler::Enter( Avatar * avatar )
{
	avatar->Send( "================================\n\r" );
	avatar->Send( "===      {WHelp   Editor{x       ===\n\r" );
	avatar->Send( "=== #help - More Information ===\n\r" );
	avatar->Send( "=== #quit - Exits Editor     ===\n\r" );
	avatar->Send( "================================\n\r" );
}

void EditHelpHandler::Exit( Avatar * avatar )
{
     delete this;
}

void EditHelpHandler::Handle( Avatar * avatar, const string &input)
{
	string checked;
	string option;
	string change;
	string buf;
	bool command = false;

	if ( input.empty () )
		return;

	checked = input;
	
	// Check to see if they're trying to
	for ( string::const_iterator cChar = input.begin(); cChar != input.end(); ++cChar )
    {
		if ( (*cChar) == '/' && cChar == input.begin() )
        {
			option = input.substr( 1, input.length() );
			if ( !strstr( input.c_str(), "quit" )  )// FIXEME: do not quit while editing
				CommandTable::Instance().Execute( avatar, option );
			return;
		}
        else if ( (*cChar) == '#' && cChar == input.begin() )
        {
			command = true;
			option = input.substr( 1, input.length() );
			checked = option;
			option.erase();
			break;
		}
        else if ( ( (*cChar) == '\n' || (*cChar) == '\r' ) && cChar == input.begin() )
        {
			checked.erase();
			break;
		}
	 }

	split( checked, option, change );

	if ( !strcasecmp( option, "quit" ) && command == true )
    {
		if ( _edit )
        {
 		 _edit->Save();
         _edit = NULL;
        }
		else
			avatar->ExitHandler();
		return;
		
	}
	else if ( !strcasecmp( option, "abort" ) && command == true )
	{
		if ( _edit )
            _edit = NULL;
		else
			avatar->ExitHandler();
		return;
    }
    else if ( ( !strcasecmp( option, "commands" ) || !strcasecmp( option, "help" ) ) )
    {
		string buf;
		if ( !_edit ) {
			buf << "Enter the name of the help file you wish to edit.\n\r";
		} else {
 	   	buf << "|------------------------------ Help ---------------------------------|\n\r";
 	   	buf << "| #commands          This help file.                                  |\n\r";
 	   	buf << "| #show              Shows what you are editing.                      |\n\r";
 	   	buf << "| #quit              Quits the Editor and saves the help file         |\n\r";
 	   	buf << "| #abort             Quits the Help Editor and -doesnt- save the file |\n\r";
 	   	buf << "| #save              Save your current progress.                      |\n\r";
 	   	buf << "| #delete            Delete the help file you're editing.             |\n\r";
 	   	buf << "|                                                                     |\n\r";
 	   	buf << "| Editing Commands                                                    |\n\r";
  		buf << "| name     <name>    Changes the help files name.                     |\n\r";
 	   	buf << "| perm     <group>   Changes the help files group.                    |\n\r";
		buf << "| author   <name>    Changes the author.                              |\n\r";
   	    buf << "| text     <text>    Changes the help files body.                     |\n\r";
 	   	buf << "|                                                                     |\n\r";
 	   	buf << "| {R*{x Commands preceded by a {B/{x will be executed as regular commands.    |\n\r";
 	   	buf << "|---------------------------------------------------------------------|\n\r\n\r";
 	   }
 	   avatar->Send( buf );
 	   return;
	}

		if ( checked.empty() || ( !strcasecmp( option, "show" ) && command == true ) )
        {
			if ( _edit )
            {
				buf << "[name: " << _edit->Get( "name" ) << "]\n\r";
				buf << "[perm: " << _edit->Get("perm") << "]\n\r";
				buf << "[author: " << _edit->Get("author") << "]\n\r";
                buf << "[text:\n\r\n\r" << _edit->Get("text") << "\n\r";
			}
            else
				buf << "You are not currently editing anything.\n\r";
			avatar->Send( buf );
			return;
		}
        else if ( _edit )
        {
            _edit->Set("last_update", Timestamp::Instance().GetDateTime() );
			if ( !strcasecmp( option, "name" ) )
            {
				string oldName = _edit->Get( "name" );

                if ( World::Instance().FindHelp(change) != NULL )
                {
                  avatar->Send("A help file with that name already exists!\n\r");
                  return;
                }

				_edit->Set( "name", change );
				avatar->Send( "Name updated.\n\r" );

				return;
			}
            else if ( !strcasecmp( option, "perm" ) )
            {
                _edit->Set("last_update", Timestamp::Instance().GetDateTime() );
				_edit->Set( "perm", change );
				avatar->Send( "Permissions updated.\n\r" );
				return;
			}
            else if ( !strcasecmp( option, "author" ) )
            {
                _edit->Set("last_update", Timestamp::Instance().GetDateTime() );
				_edit->Set( "author", change );
				avatar->Send( "Author updated.\n\r" );
				return;
			}
            else if ( !strcasecmp( option, "text" ) )
            {
                _edit->Set("last_update", Timestamp::Instance().GetDateTime() );
                _edit->Set("text", change );
				avatar->Send( "Text changed.\n\r" );
				return;
			}
			else if ( ( !strcasecmp( option, "save" ) && command == true ) )
            {
                _edit->Set("last_update", Timestamp::Instance().GetDateTime() );
				_edit->Save();
				avatar->Send( "Help file saved.\n\r" );
				return;
			}
            else if ( ( !strcasecmp( option, "delete" ) && command == true ) )
            {
				string buf;
				buf << _edit->Get( "name" ) << " has been deleted.\n\r";
    	  		avatar->Send( buf );

                // remove from db
 	            buf << "DELETE FROM help WHERE name='" << Mysql::Instance().EscapeString( _edit->Get( "name" ) ) << "'";
  	            Mysql::Instance().Query( buf.c_str() );

				// delete from mem
				delete _edit;
				
    	  		_edit = NULL;
  	    		return;
  	  	    }
		}
        else if ( !_edit )
        {
            if ( (_edit = World::Instance().FindHelp(option)) == NULL )
            {
                avatar->Send("\n\rCreating new help file...\n\r");
                string time = Timestamp::Instance().GetDateTime();

                buf << "INSERT INTO help ( name, author, last_update, creation_date ) VALUES ( '"
                << Mysql::Instance().EscapeString(option) << "', '" << Mysql::Instance().EscapeString(avatar->Get("name")) << "', '"
                << Mysql::Instance().EscapeString(time) << "', '" << Mysql::Instance().EscapeString(time) << "' )";

                if ( !Mysql::Instance().Query( buf.c_str() ) )
                  glog( "EditHelpHandler::EditHelpHandler -> Failed Query!" );
                else
                {
                  _edit = new Help(option);
                  new_file = true;
                }

            }
            else if ( avatar->Get("group").find( _edit->Get("perm") ) == string::npos)
             avatar->ExitHandler(); // exit the handler, tried to edit without being of adaquete permissions

		    _name = _edit->Get( "name" );
		    
		    buf.erase();
			buf << "You are now editing [{b" << _edit->Get( "name" ) << "{x]\n\r";
			avatar->Send( buf );

       		return;
       	}

	if ( command )
		avatar->Send( "That is an invalid # command. Try #help\n\r" );
}

string EditHelpHandler::Prompt( Avatar * avatar )
{
	return (_edit == NULL ? "Enter help file: " : ">> ");
}