#ifndef TITANPEERINGNETWORK_H
#define TITANPEERINGNETWORK_H

#include "PeeringNetwork/PeeringServerApi.h"
#include "PeeringNetwork/ObjectManager.h"

class Titan;

enum AppPacketType 
{ 
    cAppPacketNone
    , cAppPacketObjectManager       // packet that should be routed to ObjectManager for processing
};

class TitanPeeringNetwork : public PeeringNetwork::PeeringServerHandler, public PeeringNetwork::ObjectHandler
{
    public:
        TitanPeeringNetwork(Titan *titan);
        virtual ~TitanPeeringNetwork();

            /////////////////////////////////////
            // PeeringServerApi functionality
            /////////////////////////////////////
        void SetPeeringNetwork(/*gift*/ PeeringNetwork::PeeringServerApi *api);
        void GiveTime();

        void GameCreate(const char *gameName);
        void GameJoin(int gameId);

            // send to a specific peer (usually at the request of the ObjectManager::OnPeerSend callback)
        // TODO?
        //void PeerSend(int peerId, int applicationType, const char *data, int dataLen);

            // send to the entire cluster (probably won't do this as the object manager explicitly calls out everybody it wants to send to individually)
        //void ClusterSend(int applicationType, const char *data, int dataLen);           // send to cluster

        void Flush();     
        int  GetPeerID();

            /////////////////////////////////////
            // ObjectManager functionality
            /////////////////////////////////////
        int ObjectReserveId();
        void ObjectCreate(int typeId, int objectId, bool ownerLifetime, const char *fullState, int fullStateLen);
        void ObjectDestroy(int objectId);
        void ObjectBroadcast(int objectId, const char *data, int dataLen);
        void ObjectMessage(int objectId, const char *data, int dataLen);
        void ObjectTransferOwnership(int objectId, int destPeerId);
        void ObjectRequestOwnership(int objectId);
        bool ObjectIsOwner(int objectId);
        

        /////////////////////////////////////
        // external game functionality
        /////////////////////////////////////

        int GetSelfPeerId();
        int GetObjectPeerId(int objectId);

    public:
            // temporary until it is moved to the front-end
        void HackStartupNetwork(const char *playerName, const char *gameName, const char *xmlFilename, const char *recordFilename, const char *playbackFilename);

    protected:
            ///////////////////////////////////////////////////////
            // callbacks from the PeeringServerApi
            ///////////////////////////////////////////////////////
        virtual void OnTerminated(PeeringNetwork::PeeringServerApi *api);
        virtual void OnAuthenticated(PeeringNetwork::PeeringServerApi *api);
        virtual void OnGameListArrived(PeeringNetwork::PeeringServerApi *api);
        virtual void OnGameJoined(PeeringNetwork::PeeringServerApi *api);       // called in response to a create or join game request
        virtual void OnPeerAdded(PeeringNetwork::PeeringServerApi *api, int peerId);
        virtual void OnPeerRemoved(PeeringNetwork::PeeringServerApi *api, int peerId);
        virtual void OnPeerReady(PeeringNetwork::PeeringServerApi *api, int peerId);
        virtual void OnClusterReady(PeeringNetwork::PeeringServerApi *api);
        virtual void OnRoutePacket(PeeringNetwork::PeeringServerApi *api, int fromPeerId, int applicationType, const char *data, int dataLen);


            ///////////////////////////////////////////////////////
            // callback from the ObjectManager
            ///////////////////////////////////////////////////////
        virtual void OnObjectCreate(PeeringNetwork::ObjectManager *manager, int typeId, int objectId, const char *fullState, int fullStateLen);
        virtual void OnObjectReset(PeeringNetwork::ObjectManager *manager, int objectId, const char *fullState, int fullStateLen);
        virtual void OnObjectMessage(PeeringNetwork::ObjectManager *manager, int toObjectId, const char *data, int dataLen);
        virtual void OnObjectBroadcast(PeeringNetwork::ObjectManager *manager, int fromObjectId, const char *data, int dataLen);
        virtual void OnObjectDestroy(PeeringNetwork::ObjectManager *manager, int objectId);
        virtual void OnObjectRequestOwnership(PeeringNetwork::ObjectManager *manager, int objectId, int requestingPeerId);
        virtual void OnObjectTakeOwnership(PeeringNetwork::ObjectManager *manager, int objectId);
        virtual int OnObjectGetState(PeeringNetwork::ObjectManager *manager, int objectId, char *stateBuffer, int stateBufferLen);
        virtual void OnPeerSend(PeeringNetwork::ObjectManager *manager, int peerId, const char *data, int dataLen);

    protected:
        void WaitForJoinReply();

        Titan *m_titan;
        PeeringNetwork::PeeringServerApi *m_api;
        PeeringNetwork::ObjectManager *m_objectManager;
        bool m_waitingForJoinReply;
        bool m_hackAuthenticated;
        bool m_hackGameListArrived;
        bool m_terminated;
        char m_hackFilename[256];
        char m_hackGameName[256];
};


#endif
