
#include "dbconn.h"
#include "players_realms.h"
#include "fortress_skelet.h"

#ifdef _DEBUG
#ifndef DEBUG_NEW
#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
#define new DEBUG_NEW
#endif
#endif

/* indexy pro player realms - INSERT dotaz */
#define DB_INDEX_PLAYER_REALMS_INSERT_QUERY_IDREALM                 1
#define DB_INDEX_PLAYER_REALMS_INSERT_QUERY_PLNAME                  2
#define DB_INDEX_PLAYER_REALMS_INSERT_QUERY_PLLOGIN                 3
#define DB_INDEX_PLAYER_REALMS_INSERT_QUERY_PLPASSWORD              4
#define DB_INDEX_PLAYER_REALMS_INSERT_QUERY_HASBAN                  5
#define DB_INDEX_PLAYER_REALMS_INSERT_QUERY_BANLEVEL                6
#define DB_INDEX_PLAYER_REALMS_INSERT_QUERY_BANDURATION             7
#define DB_INDEX_PLAYER_REALMS_INSERT_QUERY_BANREASON               8
#define DB_INDEX_PLAYER_REALMS_INSERT_QUERY_BANTIME                 9

/* indexy pro player realms - SELECT dotaz */
#define DB_INDEX_PLAYER_REALMS_SELECT_QUERY_IDREALM                 1
#define DB_INDEX_PLAYER_REALMS_SELECT_QUERY_PLNAME                  2
#define DB_INDEX_PLAYER_REALMS_SELECT_QUERY_PLLOGIN                 3
#define DB_INDEX_PLAYER_REALMS_SELECT_QUERY_PLPASSWORD              4
#define DB_INDEX_PLAYER_REALMS_SELECT_QUERY_HASBAN                  5
#define DB_INDEX_PLAYER_REALMS_SELECT_QUERY_BANLEVEL                6
#define DB_INDEX_PLAYER_REALMS_SELECT_QUERY_BANDURATION             7
#define DB_INDEX_PLAYER_REALMS_SELECT_QUERY_BANREASON               8
#define DB_INDEX_PLAYER_REALMS_SELECT_QUERY_BANTIME                 9

#define DB_INDEX_PLAYER_REALMS_SELECT_QUERY_WHERE                   1

/* indexy pro player realms - LOGIN dotaz */
#define DB_INDEX_PLAYER_REALMS_LOGIN_QUERY_IDREALM                  1
#define DB_INDEX_PLAYER_REALMS_LOGIN_QUERY_PLNAME                   2
#define DB_INDEX_PLAYER_REALMS_LOGIN_QUERY_PLLOGIN                  3
#define DB_INDEX_PLAYER_REALMS_LOGIN_QUERY_PLPASSWORD               4

#define DB_INDEX_PLAYER_REALMS_LOGIN_QUERY_WHERE                    1

/* indexy pro player realms - DELETE dotaz */
#define DB_INDEX_PLAYER_REALMS_DELETE_QUERY_WHERE                   1

/* indexy pro player realms - UPDATE dotaz */
#define DB_INDEX_PLAYER_REALMS_UPDATE_QUERY_IDREALM                 9
#define DB_INDEX_PLAYER_REALMS_UPDATE_QUERY_PLNAME                  1
#define DB_INDEX_PLAYER_REALMS_UPDATE_QUERY_PLLOGIN                 2
#define DB_INDEX_PLAYER_REALMS_UPDATE_QUERY_PLPASSWORD              3
#define DB_INDEX_PLAYER_REALMS_UPDATE_QUERY_HASBAN                  4
#define DB_INDEX_PLAYER_REALMS_UPDATE_QUERY_BANLEVEL                5
#define DB_INDEX_PLAYER_REALMS_UPDATE_QUERY_BANDURATION             6
#define DB_INDEX_PLAYER_REALMS_UPDATE_QUERY_BANREASON               7
#define DB_INDEX_PLAYER_REALMS_UPDATE_QUERY_BANTIME                 8


/* indexy pro player realms - BSLIST dotaz */
#define DB_INDEX_PLAYER_REALMS_BSLIST_QUERY_IDFORTRESS              1
#define DB_INDEX_PLAYER_REALMS_BSLIST_QUERY_FORTRESSTYPE            2
#define DB_INDEX_PLAYER_REALMS_BSLIST_QUERY_CONTROLLABLE            3

#define DB_INDEX_PLAYER_REALMS_BSLIST_QUERY_WHERE                   1

// --------------------------------

#define DB_PLAYER_REALMS_INITIALIZE_QUERY "SELECT IDREALM, PLLOGIN, PLNAME FROM PLAYERS ORDER BY IDREALM DESC"

#define DB_INDEX_PLAYER_REALMS_INITIALIZE_IDITEM                            1
#define DB_INDEX_PLAYER_REALMS_INITIALIZE_LOGIN                             2
#define DB_INDEX_PLAYER_REALMS_INITIALIZE_NAME                              3

// --------------------------------
// --------------------------------

#define DB_INDEX_REALM_DELETE_LIST_WHERE                     1
#define DB_INDEX_REALM_INSERT_LIST_IDREALM                   1
#define DB_INDEX_REALM_INSERT_LIST_IDITEMOFLIST              2

// --------------------------------

#define DB_INDEX_REALM_SELECT_LIST_WHERE                     1
#define DB_INDEX_REALM_SELECT_LIST_IDITEMOFLIST              1

// --------------------------------

static void __load_dtIdentifiersList_from_dblist(dtIdentifier ID, dbRealmList& fl, dtIdentifierVector& il)
{
    /* nacteme query a smazeme idetifier list */
    IBPP :: Statement& s = fl.getFL_SELECT();
    il.clear();

	try
	{
        s->Set(DB_INDEX_REALM_SELECT_LIST_WHERE, (int64_t)ID);
		s->Execute();

        while (s->Fetch())
        {
            int64_t data;
            s->Get(DB_INDEX_REALM_SELECT_LIST_IDITEMOFLIST, data); il.push_back((dtIdentifier)data);
        }

	}
	catch (IBPP :: Exception& e)
	{
		errExceptionError( e.what());
	}
}

// --------------------------------

static void __store_dtIdentifiersList_to_dblist(dtIdentifier ID, dbRealmList& fl, dtIdentifierVector& il)
{
    /* nacteme query a smazeme idetifier list */
    IBPP :: Statement& r = fl.getFL_DELETE();
    IBPP :: Statement& i = fl.getFL_INSERT();

	try
	{
        r->Set(DB_INDEX_REALM_DELETE_LIST_WHERE, (int64_t)ID);
		r->Execute();

        for (dtIdentifierVector :: const_iterator iter = il.begin(); iter != il.end(); iter++)
        {
            i->Set(DB_INDEX_REALM_INSERT_LIST_IDREALM,    (int64_t)ID);
            i->Set(DB_INDEX_REALM_INSERT_LIST_IDITEMOFLIST,  (int64_t)(*iter));
            i->Execute();
        }
	}
	catch (IBPP :: Exception& e)
	{
		errExceptionError( e.what());
	}
}

// --------------------------------

void cacheRealmsListClass :: DB_Initialize()
{
    // priprav cache list a i nahraj data do indexu
    IBPP :: Database& db    = actx->db.getDatabase();
    IBPP :: Transaction& tr = actx->db.getTransaction();
    
    IBPP :: Statement s = IBPP :: StatementFactory(db, tr, DB_PLAYER_REALMS_INITIALIZE_QUERY);

	try
	{
        s->Execute();

        // nacteme, jak velky potrebujeme ten list
        if (s->Fetch())
        {
            int64_t d;
            s->Get(DB_INDEX_PLAYER_REALMS_INITIALIZE_IDITEM, d);
            expand((unsigned long)d + 1, identifiersReusable());       
        
            // postupne nacitame polozky
            do
            {
                int64_t itemId;
                std :: string login, name;
                s->Get(DB_INDEX_PLAYER_REALMS_INITIALIZE_IDITEM,    itemId);
                s->Get(DB_INDEX_PLAYER_REALMS_INITIALIZE_LOGIN,     login);
                s->Get(DB_INDEX_PLAYER_REALMS_INITIALIZE_NAME,      name);

                // zaneseme login do indexu loginu
                logins[login]   = (dtIdentifier)itemId;
                names[name]     = (dtIdentifier)itemId;

                // pote oznacime polozku v listu, ze je v databazi
                data[(unsigned long)itemId].first = DATA_IN_DATABASE_ONLY;
                freeIDs.erase((dtIdentifier)itemId);
            } while (s->Fetch());
        }

        s->Close();
	}
	catch (std :: bad_alloc e)
	{
		errExceptionError(e.what());
	}   
	catch (IBPP :: Exception& e)
	{
		errExceptionError( e.what());
	}
}

// --------------------------------

void cacheRealmsListClass :: DB_Remove( unsigned long ID )
{
	/* smaz vsechny uzly uzivatele */
    IBPP :: Statement& s = actx->db.getPlayerRealmQueryDELETE();	
    s->Set(DB_INDEX_PLAYER_REALMS_DELETE_QUERY_WHERE, (int64_t)ID);
	try
	{
		s->Execute();
	}
	catch (IBPP :: Exception& e)
	{
		errExceptionError( e.what());
	}
}

// --------------------------------

void cacheRealmsListClass :: DB_Load( unsigned long ID )
{
	// nahraj data itemu 
	IBPP :: Statement& s = actx->db.getPlayerRealmQuerySELECT();

	try
	{
        s->Set(DB_INDEX_PLAYER_REALMS_SELECT_QUERY_WHERE, (int64_t)ID);
		s->Execute();

		// jestli je to v databazi, nahraj to, jinak oznam chybu 
		if (s->Fetch()) 
		{
            realmClass* f = new realmClass();
			f->setID(ID);
            f->DB_Load(ID);

            // nahrajeme zakladny a lode
            IBPP :: Statement& lst = actx->db.getPlayerRealmQueryBSLIST();
            try
            {
                lst->Set(DB_INDEX_PLAYER_REALMS_BSLIST_QUERY_WHERE, (int64_t) ID);
                lst->Execute();

                while (lst->Fetch())
                {
                    int64_t data;
                    dtIdentifier fortressID;
                    fortressesTypes fType;
                    bool controllable;

                    lst->Get(DB_INDEX_PLAYER_REALMS_BSLIST_QUERY_IDFORTRESS,    data);  fortressID      = (dtIdentifier) data;
                    lst->Get(DB_INDEX_PLAYER_REALMS_BSLIST_QUERY_FORTRESSTYPE,  data);  fType           = (fortressesTypes) data;
                    lst->Get(DB_INDEX_PLAYER_REALMS_BSLIST_QUERY_CONTROLLABLE,  data);  controllable    = data != 0;

                    if (!controllable)
                    {
                        f->DB_InitUnct(fortressID);
                    }
                    else
                    {
                        switch (fType)
                        {
                        case FT_BASE:
                            f->DB_InitBase(fortressID);
                            break;
                        case FT_SHIP:
                            f->DB_InitShip(fortressID);
                            break;
                        default:
                            errExceptionError("Invalid fortress type!");
                        }
                    }
                }
            }
	        catch (IBPP :: Exception& e)
	        {
		        errExceptionError( e.what());
	        }

            data[ID] = make_pair(DATA_SYNCHRONIZED, f);
		} else
		{
			errExceptionError( "Realm load failed - no record %u in DB", (unsigned long long)ID);
		}
	}
	catch (std :: bad_alloc e)
	{
		errExceptionError(e.what());
	}   
	catch (IBPP :: Exception& e)
	{
		errExceptionError( e.what());
	}
}

// --------------------------------

void realmClass :: DB_Load(unsigned long ID)
{
	// predpokladame, ze dotaz je pripraveny pro cteni dat
	IBPP :: Statement& s = actx->db.getPlayerRealmQuerySELECT();
    setID(ID);

    try
    {
        int64_t data;

        bool hasban;
        int banlevel, banduration;
        std :: string banreason;
        double bantime;

        s->Get(DB_INDEX_PLAYER_REALMS_SELECT_QUERY_PLNAME,          playerName_);
        s->Get(DB_INDEX_PLAYER_REALMS_SELECT_QUERY_PLLOGIN,         login_);          
        s->Get(DB_INDEX_PLAYER_REALMS_SELECT_QUERY_PLPASSWORD,      password_); 
		s->Get(DB_INDEX_PLAYER_REALMS_SELECT_QUERY_HASBAN,          data);          hasban = data != 0;
		s->Get(DB_INDEX_PLAYER_REALMS_SELECT_QUERY_BANLEVEL,        banlevel);
		s->Get(DB_INDEX_PLAYER_REALMS_SELECT_QUERY_BANDURATION,     banduration);
		s->Get(DB_INDEX_PLAYER_REALMS_SELECT_QUERY_BANREASON,       banreason);
		s->Get(DB_INDEX_PLAYER_REALMS_SELECT_QUERY_BANTIME,         bantime);

        if (hasban)
        {
            if (ban_ != NULL)
            {
                ban_->setBanParameters(banlevel, banduration, banreason, bantime);
            }
            else
            {
                ban_ = new banClass(banlevel, banduration, banreason, bantime);
            }
        }

        // nahrajeme strom vedy
        getScientificTree()->DBLoad(ID);

        // nahrajeme objevene hvezdne soustavy
        __load_dtIdentifiersList_from_dblist(ID, actx->db.getPlayerRealmDSList(), discoveredSolarSystems_);
    }
	catch (IBPP :: Exception& e)
	{
		errExceptionError( e.what());
	}
};

// --------------------------------

void realmClass :: DB_Insert(unsigned long ID)
{
	// predpokladame, ze dotaz je pripraveny pro cteni dat
	IBPP :: Statement& s = actx->db.getPlayerRealmQueryINSERT();
    setID(ID);

    try
    {
        s->Set(DB_INDEX_PLAYER_REALMS_INSERT_QUERY_IDREALM,         (int64_t)ID);
        s->Set(DB_INDEX_PLAYER_REALMS_INSERT_QUERY_PLNAME,          playerName_);
        s->Set(DB_INDEX_PLAYER_REALMS_INSERT_QUERY_PLLOGIN,         login_);          
        s->Set(DB_INDEX_PLAYER_REALMS_INSERT_QUERY_PLPASSWORD,      password_); 

        if (ban_)
        {
		    s->Set(DB_INDEX_PLAYER_REALMS_INSERT_QUERY_HASBAN,              1);
            s->Set(DB_INDEX_PLAYER_REALMS_INSERT_QUERY_BANLEVEL,			ban_->getLevel());
            s->Set(DB_INDEX_PLAYER_REALMS_INSERT_QUERY_BANDURATION,			ban_->getDurationInDays());
            s->Set(DB_INDEX_PLAYER_REALMS_INSERT_QUERY_BANREASON,			ban_->getReason());
            s->Set(DB_INDEX_PLAYER_REALMS_INSERT_QUERY_BANTIME,			    ban_->getTimePlaced());
        }
        else
        {
		    s->Set(DB_INDEX_PLAYER_REALMS_INSERT_QUERY_HASBAN,              0);
		    s->SetNull(DB_INDEX_PLAYER_REALMS_INSERT_QUERY_BANLEVEL);
		    s->SetNull(DB_INDEX_PLAYER_REALMS_INSERT_QUERY_BANDURATION);
		    s->SetNull(DB_INDEX_PLAYER_REALMS_INSERT_QUERY_BANREASON);
		    s->SetNull(DB_INDEX_PLAYER_REALMS_INSERT_QUERY_BANTIME);
        }

        s->Execute();

        // insertujeme strom vedy
        getScientificTree()->DBInsert(ID);

        // ulozime objevene hvezdne soustavy
        __store_dtIdentifiersList_to_dblist(ID, actx->db.getPlayerRealmDSList(), discoveredSolarSystems_);
    }
	catch (IBPP :: Exception& e)
	{
		errExceptionError( e.what());
	}
};

// --------------------------------

void realmClass :: DB_Save(unsigned long ID)
{
	// predpokladame, ze dotaz je pripraveny pro cteni dat
	IBPP :: Statement& s = actx->db.getPlayerRealmQueryUPDATE();
    setID(ID);

    try
    {
        s->Set(DB_INDEX_PLAYER_REALMS_UPDATE_QUERY_IDREALM,         (int64_t)ID);
        s->Set(DB_INDEX_PLAYER_REALMS_UPDATE_QUERY_PLNAME,          playerName_);
        s->Set(DB_INDEX_PLAYER_REALMS_UPDATE_QUERY_PLLOGIN,         login_);          
        s->Set(DB_INDEX_PLAYER_REALMS_UPDATE_QUERY_PLPASSWORD,      password_);  

        if (ban_)
        {
		    s->Set(DB_INDEX_PLAYER_REALMS_UPDATE_QUERY_HASBAN,              1);
            s->Set(DB_INDEX_PLAYER_REALMS_UPDATE_QUERY_BANLEVEL,			ban_->getLevel());
            s->Set(DB_INDEX_PLAYER_REALMS_UPDATE_QUERY_BANDURATION,			ban_->getDurationInDays());
            s->Set(DB_INDEX_PLAYER_REALMS_UPDATE_QUERY_BANREASON,			ban_->getReason());
            s->Set(DB_INDEX_PLAYER_REALMS_UPDATE_QUERY_BANTIME,			    ban_->getTimePlaced());
        }
        else
        {
		    s->Set(DB_INDEX_PLAYER_REALMS_UPDATE_QUERY_HASBAN,              0);
		    s->SetNull(DB_INDEX_PLAYER_REALMS_UPDATE_QUERY_BANLEVEL);
		    s->SetNull(DB_INDEX_PLAYER_REALMS_UPDATE_QUERY_BANDURATION);
		    s->SetNull(DB_INDEX_PLAYER_REALMS_UPDATE_QUERY_BANREASON);
		    s->SetNull(DB_INDEX_PLAYER_REALMS_UPDATE_QUERY_BANTIME);
        }

        s->Execute();

        // ulozime strom vedy
        getScientificTree()->DBSave(ID);

        // ulozime objevene hvezdne soustavy
        __store_dtIdentifiersList_to_dblist(ID, actx->db.getPlayerRealmDSList(), discoveredSolarSystems_);
    }
	catch (IBPP :: Exception& e)
	{
		errExceptionError( e.what());
	}
};

// --------------------------------

