///////////////////////////////////////////////////////////
///////////////// Have an itch? Scratch it! ///////////////
///////////////////////// SCRATCH /////////////////////////
/////////////////////  A MUD  Server   ////////////////////
///////////////////// By: Jared Devall ////////////////////
/////////////////////      Thanks:     ////////////////////
/////////////////////  DIKU/Merc/ROM   ////////////////////
///////////////////// Aetas/Deus Gang  ////////////////////
/////////////////////       Beej       ////////////////////
///////////////////////////////////////////////////////////

#include <mysql/mysql.h>
#include <iostream>
#include "smysql.h"
#include "stringutil.h"

using namespace std;


Mysql::Mysql ( const char * hostname, const char * username, const char * password, const char * dbname ): _dbinstance( new MYSQL ) {
	// mysql_connect is deprecated, made the change
	mysql_init( _dbinstance );
	if ( !mysql_real_connect( _dbinstance, hostname, username, password, dbname, 0, NULL, 0 ) ) 
		cerr << "Error connecting to database (user: " << username << ", hostname: " << hostname << ", password: " << password << ", dbname: " << dbname << ")" << endl;
}

Mysql::~Mysql () {
	mysql_close( _dbinstance );  
    delete _dbinstance;
}


bool Mysql::Query ( const char * query ) {
  if ( mysql_query( _dbinstance, query ) != 0 )
  	return false;

  // -1 is an error condition.
  return mysql_affected_rows( _dbinstance ) >= 0;
}

bool Mysql::RealQuery( const char * query ) {	
	if ( mysql_real_query( _dbinstance, query, strlen( query ) ) )
		return false;
	
	// -1 is an error condition.	
	return mysql_affected_rows( _dbinstance ) >= 0;
}

// Mysql's escape_string function was crashing on me so I made my own. It seems to work
// fine. 
string Mysql::EscapeString( const string &to_escape ) {
	string buf;
	
	for ( string::const_iterator c = to_escape.begin(); c != to_escape.end(); ++c ) {
		if ( (*c) == '\'' ) {
			buf << "\\'";
		} else if ( (*c) == '\"' ) {
			buf << "\\\"";
		} else if ( (*c) == '\0' ) {
			buf << "\\0";
		} else if ( (*c) == '\b' ) {
			buf << "\\b";
		} else if ( (*c) == '\r' ) {
			buf << "\\r";
		} else if ( (*c) == '\t' ) {
			buf << "\\t";
		} else if ( (*c) == '_' ) {
			buf << "\\_";
		} else if ( (*c) == '\a' ) {
			buf << "\\a";		
		} else {
			buf << (*c);
		}
	}
	return buf;
}

// Returns the affected rows of a query
int Mysql::QueryRows( const char * query ) {
	if ( mysql_query( _dbinstance, query ) != 0 )
		return false;
		
	return mysql_affected_rows( _dbinstance );
}
/*
 * Load is used when selecting stuff from the database.
 * The information is stuck into map, which is stuck into a vector
 * In the map, the first std::string is the field name, the second
 * is the value.
 */
bool Mysql::Load( const char * query ) {
	_info.clear();
	if ( mysql_query( _dbinstance, query ) != 0 )
       return false;

    MYSQL_RES *result;
    if ( !( result = mysql_store_result( _dbinstance ) ) )
       return false;

	if ( mysql_affected_rows( _dbinstance ) <= 0 )
		return false;

		
    MYSQL_ROW row;
    unsigned int num_fields = 0;
    LMAP info;
    while ( ( row = mysql_fetch_row( result ) ) ) {
    	num_fields = mysql_num_fields( result );
    	for ( unsigned int i = 0; i < num_fields; ++i) {
      	if ( !row[i] ) 
      	   continue;
          info.insert( make_pair( result->fields[i].name, row[i] ) );
        }
        _info.push_back( info );
        info.clear();
    }
  mysql_free_result(result);

  return num_fields != 0;
}