#include "NetworkManager.h"
#include "Titan.h"
#include "registry.h"


NetworkManager::NetworkManager(Titan *titan)
{
    m_pTitan = titan;
    m_objectManager = new PeeringNetwork::ObjectManager(this);
    m_peeringApi = NULL;
}

NetworkManager::~NetworkManager()
{
    delete m_peeringApi;
    delete m_objectManager;
}

void NetworkManager::GiveTime()
{
    if (m_peeringApi != NULL)
    {
        m_peeringApi->GiveTime();
    }
}

void NetworkManager::Connect(const char *address, const char *name, const char *password)
{
    m_peeringApi = new PeeringNetwork::PeeringServerApi(this, address, name, password, 0);
}

    ////////////////////////////////////////////////////////////////////////////
    // api handlers
    ////////////////////////////////////////////////////////////////////////////

void NetworkManager::OnTerminated(PeeringNetwork::PeeringServerApi *api)
{
}

void NetworkManager::OnAuthenticated(PeeringNetwork::PeeringServerApi *api)
{
        // request game list (so we can join an existing game)
    m_peeringApi->RequestGameList();
}

void NetworkManager::OnGameListArrived(PeeringNetwork::PeeringServerApi *api)
{
    const SyEmbeddedListOwn<PeeringNetwork::PacketGameEntry> *list = m_peeringApi->GetGameList();
    PeeringNetwork::PacketGameEntry *cur = list->First();
    if (cur != NULL)
    {
            // HACK: for now join first game on the list
        m_peeringApi->RequestGameJoin(cur->m_gameId);
    }
    else
    {
            // HACK: for now if there are no games listed, just create a new game (it will auto join)
        m_peeringApi->RequestGameCreate("Test Game");
    }
}

void NetworkManager::OnGameJoined(PeeringNetwork::PeeringServerApi *api)
{
    m_objectManager->SetSelfPeerId(m_peeringApi->GetSelfPeerId());
}

void NetworkManager::OnPeerAdded(PeeringNetwork::PeeringServerApi *api, int peerId)
{
    m_objectManager->PeerAdded(peerId);
}

void NetworkManager::OnPeerRemoved(PeeringNetwork::PeeringServerApi *api, int peerId)
{
    m_objectManager->PeerRemoved(peerId);
}

void NetworkManager::OnPeerReady(PeeringNetwork::PeeringServerApi *api, int peerId)
{
}

void NetworkManager::OnRoutePacket(PeeringNetwork::PeeringServerApi *api, int fromPeerId, int applicationType, const char *data, int dataLen)
{
        // application level packet arrived off the cluster
    switch (applicationType)
    {
        case cAppPacketObjectManager:
        {
                // packet is destined for object manager, so forward it for processing
            m_objectManager->ProcessMessage(data, dataLen);
            break;
        }
        default:
        {
            SyAssert(0);    // unknown application-level packet
            break;
        }
    }
}

void NetworkManager::OnClusterReady(PeeringNetwork::PeeringServerApi *api)
{
}


    ////////////////////////////////////////////////////////////////////////////
    // object handlers
    ////////////////////////////////////////////////////////////////////////////

void NetworkManager::OnObjectCreate(PeeringNetwork::ObjectManager *manager, int typeId, int objectId, const char *fullState, int fullStateLen)
{
  m_pTitan->GetRegistry()->NetworkCreate((cGameObject::tObjectType)typeID,objectId,fullState,fullStateLen);
}

void NetworkManager::OnObjectReset(PeeringNetwork::ObjectManager *manager, int objectId, const char *fullState, int fullStateLen)
{
  m_pTitan->GetRegistry()->NetworkSetState(objectID,fullState,fullStateLen);
}

void NetworkManager::OnObjectDestroy(PeeringNetwork::ObjectManager *manager, int objectId)
{
  m_pTitan->GetRegistry()->NetworkDelete(objectId);
}

void NetworkManager::OnObjectMessage(PeeringNetwork::ObjectManager *manager, int objectId, const char *data, int dataLen)
{
        // TODO: send message to specified object for processing
}

void NetworkManager::OnObjectTakeOwnership(PeeringNetwork::ObjectManager *manager, int objectId)
{
        // TODO: we might do something like create an brain-object and attach it to the object at this point
}

int NetworkManager::OnObjectGetState(PeeringNetwork::ObjectManager *manager, int objectId, char *stateBuffer, int stateBufferLen)
{
  return mpTitan->GetRegistry()->NeworkGetState(objectID, stateBuffer,stateBufferLen);
}

void NetworkManager::OnPeerSend(PeeringNetwork::ObjectManager *manager, int peerId, const char *data, int dataLen)
{
    if (m_peeringApi != NULL)
    {
        m_peeringApi->PeerSend(peerId, cAppPacketObjectManager, data, dataLen);
    }
}
