// CustomZoneSample.cpp : Defines the entry point for the DLL application.
//

#include "bzfsAPI.h"
#include "plugin_utils.h"

// The custom zone we'll be making for this plug-in and we'll be extending a class provided by the API.
// The class provided in the API handles all of the logic handling rectangular and circular zones.
class MsgZone : public bz_CustomZoneObject
{
public:
    // Our custom constructor will call the parent constructor so we can setup default positions
    // for the zone
    MsgZone() : bz_CustomZoneObject(), flag("US")
    {
    }

    // Custom fields that are unique to our zone so we can build on top of the class we're extending
    std::string message;
    std::string flag;
};

class CustomZoneSample : public bz_Plugin, bz_CustomMapObjectHandler
{
public:
    virtual const char* Name ()
    {
        return "Custom Zone Sample";
    }
    virtual void Init ( const char* config );
    virtual void Event ( bz_EventData *eventData );
    virtual void Cleanup ( void );

    virtual bool MapObject (bz_ApiString object, bz_CustomMapObjectInfo *data);

    std::vector<MsgZone> msgZones;

    bool messageSentTo[256];
};

BZ_PLUGIN(CustomZoneSample)

void CustomZoneSample::Init (const char* /*commandLine*/)
{
    Register(bz_ePlayerUpdateEvent);

    // Whenever a player enters a zone and is carrying a specified flag, they will receive the specified message
    bz_registerCustomMapObject("msgzone", this);
}

void CustomZoneSample::Cleanup (void)
{
    Flush();

    bz_removeCustomMapObject("msgzone");
}

bool CustomZoneSample::MapObject (bz_ApiString object, bz_CustomMapObjectInfo *data)
{
    if (object != "MSGZONE" || !data)
        return false;

    // The new zone we just found and we'll be storing in our vector of zones
    MsgZone newZone;

    // This function will parse the attributes that are handled by bz_CustomZoneObject which
    // handles rectangular and circular zones
    //
    // For rectangular zones:
    //   - position
    //   - size
    //   - rotation
    //
    // For circular zones:
    //   - position
    //   - height
    //   - radius
    //
    // This also handles BBOX and CYLINDER fields but they have been deprecated and will be
    // removed in the future
    newZone.handleDefaultOptions(data);

    // Loop through the object data
    for (unsigned int i = 0; i < data->data.size(); i++)
    {
        std::string line = data->data.get(i).c_str();

        bz_APIStringList *nubs = bz_newStringList();
        nubs->tokenize(line.c_str(), " ", 0, true);

        if (nubs->size() > 0)
        {
            std::string key = bz_toupper(nubs->get(0).c_str());

            // These are our custom fields in the MsgZone class
            if (key == "MESSAGE" && nubs->size() > 1)
                newZone.message = nubs->get(1).c_str();
            else if (key == "FLAG" && nubs->size() > 1)
                newZone.flag = nubs->get(1).c_str();
        }

        bz_deleteStringList(nubs);
    }

    msgZones.push_back(newZone);

    return true;
}

void CustomZoneSample::Event (bz_EventData *eventData)
{
    switch (eventData->eventType)
    {
    case bz_ePlayerUpdateEvent: // This event is called each time a player sends an update to the server
    {
        bz_PlayerUpdateEventData_V1* updateData = (bz_PlayerUpdateEventData_V1*)eventData;

        // Loop through all of our custom zones
        for (unsigned int i = 0; i < msgZones.size(); i++)
        {
            // Use the pointInZone(float pos[3]) function provided by the bz_CustomZoneObject to check if the position
            // of the player is inside of the zone. This function will automatically handle the logic if the zone is a
            // rectangle (even if it's rotated) or a circle
            if (msgZones[i].pointInZone(updateData->state.pos) && bz_getPlayerFlagID(updateData->playerID) >= 0)
            {
                // If the player has the flag specified in the zone, send them a message and remove their flag
                if (strcmp(bz_getPlayerFlag(updateData->playerID), msgZones[i].flag.c_str()) == 0)
                {
                    bz_sendTextMessage(BZ_SERVER, updateData->playerID, msgZones[i].message.c_str());
                    bz_removePlayerFlag(updateData->playerID);
                }
            }
        }
    }
    break;

    default:
        break;
    }
}

// Local Variables: ***
// mode: C++ ***
// tab-width: 4 ***
// c-basic-offset: 4 ***
// indent-tabs-mode: nil ***
// End: ***
// ex: shiftwidth=4 tabstop=4
