// Name     : Persistent container close event
// Purpose  : Called when a player closes a persistent container
// Author   : Ingmar Stieger - Heavily altered by: Josh Dalton (Lanthar D'Alton)
// Modified : February 25, 2003

// This file is licensed under the terms of the
// GNU GENERAL PUBLIC LICENSE (GPL) Version 2

#include "aps_include"

// Stackables are handled differently to decrease number of queries.
// We can trust lowercase tag here if no resref b/c it has already been tested
// by the copycheck function.
int GetIsItemStackable(object oItem)
{
    int iType = GetBaseItemType(oItem);
    if (iType == BASE_ITEM_GEM || iType == BASE_ITEM_POTIONS ||
        iType == BASE_ITEM_HEALERSKIT || iType == BASE_ITEM_THIEVESTOOLS ||
        iType == BASE_ITEM_SCROLL || iType == BASE_ITEM_ARROW ||
        iType == BASE_ITEM_BOLT || iType == BASE_ITEM_BULLET ||
        iType == BASE_ITEM_DART || iType == BASE_ITEM_THROWINGAXE ||
        iType == BASE_ITEM_SHURIKEN || iType == BASE_ITEM_GOLD)
        return TRUE;
    else
        return FALSE;
}

string GetTableIndexKey()
{
    object oPC=GetLocalObject(OBJECT_SELF, "LastUsedBy");
    string sVaultTag;
    string sPlayer;
    string sTag;

    sVaultTag=GetTag(OBJECT_SELF);
    if (GetIsPC(oPC))
    {
        sPlayer = SQLEncodeSpecialChars(GetPCPlayerName(oPC));
        sTag = SQLEncodeSpecialChars(GetName(oPC));
    }
    else
    {
        sPlayer = SQLEncodeSpecialChars(GetName(oPC));
        sTag = GetTag(oPC);
    }

    string sSQL = " player='" + sPlayer + "' AND tag='" + sTag + "' AND container='" + sVaultTag + "'";
    return sSQL;
}

// Add item to the container
// We can trust lowercase tag here if no resref b/c it has already been tested
// by the copycheck function.
void addItem(string sContainerTag, object oItem)
{
    string sSQL;
    string id = IntToString(GetIdentified(oItem));
    string rr=GetResRef(oItem);
    object oPC=GetLocalObject(OBJECT_SELF, "LastUsedBy");
    string sVaultTag;
    string sPlayer;
    string sTag;

    sVaultTag=GetTag(OBJECT_SELF);
    if (GetIsPC(oPC))
    {
        sPlayer = SQLEncodeSpecialChars(GetPCPlayerName(oPC));
        sTag = SQLEncodeSpecialChars(GetName(oPC));
    }
    else
    {
        sPlayer = SQLEncodeSpecialChars(GetName(oPC));
        sTag = GetTag(oPC);
    }
    if(rr=="")
    {
        rr=GetTag(oItem);
        rr=GetStringLowerCase(rr);
    }
    // lookup item
    sSQL = "SELECT * FROM vault_items WHERE" + GetTableIndexKey() +
           " AND item='" + rr + "' AND identified=" + id;
    SQLExecDirect(sSQL);

    if (SQLFirstRow() == SQL_SUCCESS)
    {
        // existant, increment item counter in existing row
        int iCount = StringToInt(SQLGetData(5)) + 1;
        sSQL = "UPDATE vault_items SET count=" + IntToString(iCount) +
               " WHERE" + GetTableIndexKey() +
               " AND item='" + rr + "' AND identified=" + id;
        SQLExecDirect(sSQL);
    }
    else
    {
        // not existant, add new row
        sSQL = "INSERT INTO vault_items (player,tag,container,item,count,identified) VALUES " +
               "('" + sPlayer + "','" + sTag + "','" + sContainerTag + "','" + rr + "',1," + id + ")";
        SQLExecDirect(sSQL);
    }
}

// Add item to the container
void addStack(string sContainerTag, object oItem, int iStackCount)
{
    string sSQL;
    string id = IntToString(GetIdentified(oItem));
    string rr=GetResRef(oItem);
    object oPC=GetLocalObject(OBJECT_SELF, "LastUsedBy");
    string sVaultTag;
    string sPlayer;
    string sTag;

    sVaultTag=GetTag(OBJECT_SELF);
    if (GetIsPC(oPC))
    {
        sPlayer = SQLEncodeSpecialChars(GetPCPlayerName(oPC));
        sTag = SQLEncodeSpecialChars(GetName(oPC));
    }
    else
    {
        sPlayer = SQLEncodeSpecialChars(GetName(oPC));
        sTag = GetTag(oPC);
    }
    if(rr=="")
    {
        rr=GetTag(oItem);
        rr=GetStringLowerCase(rr);
    }
    // lookup item
    sSQL = "SELECT * FROM vault_items WHERE" + GetTableIndexKey() +
           " AND item='" + rr + "' AND identified=" + id;
    SQLExecDirect(sSQL);

    if (SQLFirstRow() == SQL_SUCCESS)
    {
        // existant, increment item counter in existing row
        int iCount = StringToInt(SQLGetData(5)) + iStackCount;
        sSQL = "UPDATE vault_items SET count=" + IntToString(iCount) +
               " WHERE" + GetTableIndexKey() +
               " AND item='" + rr + "' AND identified=" + id;

        SQLExecDirect(sSQL);
    }
    else
    {
        // not existant, add new row
        sSQL = "INSERT INTO vault_items (player,tag,container,item,count,identified) VALUES " +
               "('" + sPlayer + "','" + sTag + "','" + sContainerTag + "','" + rr + "'," +
               IntToString(iStackCount) + "," + id + ")";
        SQLExecDirect(sSQL);
    }
}

int checkItem(object oItem)
{
    int retval=FALSE;
    object oWP=GetObjectByTag("WP_ITEM_TEST");  //This waypoint MUST exist.
    if(oWP!=OBJECT_INVALID)
    {
        string rr=GetResRef(oItem);
        string tag=GetTag(oItem);
        if(rr!="")
        {
            int type=GetObjectType(oItem);
            if(type!=OBJECT_TYPE_INVALID)
            {
                object oCopy=CreateObject(type, rr, GetLocation(oWP), FALSE);
                if(oCopy!=OBJECT_INVALID)
                {
                    retval=TRUE;
                    DestroyObject(oCopy);
                }
            }
        }
        else if(tag!="")
        {
            int type=GetObjectType(oItem);
            if(type!=OBJECT_TYPE_INVALID)
            {
                object oCopy=CreateObject(type, tag, GetLocation(oWP), FALSE);
                if(oCopy!=OBJECT_INVALID)
                {
                    retval=TRUE;
                    DestroyObject(oCopy);
                }
            }
        }
    }
    return retval;
}

void main()
{
    if(!SQLCheckDB() || !USE_DATABASE)//just fail if the database isn't there.
        return;
//  SetLocked(OBJECT_SELF, 1);  //lock to make sure they don't interrupt this.
    object oItem=GetFirstItemInInventory(OBJECT_SELF);
    string tag=GetTag(OBJECT_SELF);
    string sSQL;
    if(GetLocalInt(OBJECT_SELF, "began_empty"))
    {
        //first clean the database of existing stored data.
        sSQL = "SELECT * FROM vault_items WHERE" + GetTableIndexKey();
        SQLExecDirect(sSQL);
        if(SQLFirstRow()==SQL_SUCCESS)
        {   //cleanse the database for this chest.
            sSQL="DELETE FROM vault_items WHERE" + GetTableIndexKey();
            SQLExecDirect(sSQL);
        }
    }
    DeleteLocalInt(OBJECT_SELF, "began_empty");
    while(GetIsObjectValid(oItem))
    {
        if(checkItem(oItem))    //make sure we can create these.
        {
            if(GetIsItemStackable(oItem))
            {
                int iStack=GetNumStackedItems(oItem);
                addStack(tag, oItem, iStack);
            }
            else
                addItem(tag, oItem);
            DestroyObject(oItem);
        }
        else
        {
            object oOwner=GetLocalObject(oItem, "owner");   //stored on item.
            if(oOwner!=OBJECT_INVALID)
            {
                SendMessageToPC(oOwner, "This item was not able to be stored here.");
                ActionGiveItem(oItem, oOwner);
            }
            else    //try to get a valid location and drop the item outside the chest.
            {
                oOwner=GetLocalObject(OBJECT_SELF, "LastUsedBy");   //stored on chest.
                if(oOwner!=OBJECT_INVALID)
                {
                    SendMessageToPC(oOwner, "This item was not able to be stored here.");
                    ActionGiveItem(oItem, oOwner);
                }
            }
        }
        oItem=GetNextItemInInventory(OBJECT_SELF);
    }
    DeleteLocalObject(OBJECT_SELF, "LastUsedBy");
//  SetLocked(OBJECT_SELF, 0);  //lock to make sure they don't interrupt this.
}