/*
 * PVVMUD a 3D MUD
 * Copyright (C) 1998-1999  Programvareverkstedet (pvv@pvv.org)
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */
#include "pvvmud.H"
#include "srvworld.H"
#include "srvlistenerlist.H"
#include "srvworldmanager.H"
#include "player.H"
#include "mud.H"

CSrvWorld::CSrvWorld(CMud * mud):CWorldWorld(){
  m_listenerList = new CSrvListenerList();
  m_nextObjectId = 10000; // User defined id's under 10000
  m_mud = mud;
}

CSrvWorld::~CSrvWorld(){
  delete m_listenerList;
}

CListener * CSrvWorld::getListener(){
  return getListenerList();
}

CMud * CSrvWorld::getMud(){
  return m_mud;
}

CWorldObject * CSrvWorld::newObject(char * objectName,DWORD objectId, 
                                    CWorldObject * parent, DWORD geometryId,const CPosition & position, const CDirection & direction )
{

  if (parent == NULL){
    return new CSrvObject(objectId,this,geometryId,position,direction);
  } 

  if (strcmp(objectName,"player")==0){
    cdebug << "New player " << objectId << " geometry " << geometryId << "\n";
    return new CPlayer(objectId,parent,geometryId,position,direction);
  }

  // Default return new SrvObject
  cdebug << "New object " << objectId << " geometry " << geometryId << "\n";
  return new CSrvObject(objectId,parent,geometryId,position,direction);

}

DWORD CSrvWorld::getNewObjectId(){
  return m_nextObjectId++;
}

void CSrvWorld::addListener( CSrvWorldManager * listener ){
  m_listenerList->add( listener );
}

void CSrvWorld::removeListener( CSrvWorldManager * listener ){
  m_listenerList->remove( listener );
}

CSrvListenerList * CSrvWorld::getListenerList(){
  return m_listenerList;
}

void CSrvWorld::sendWorld( CSrvWorldManager * listener ){
  listener->sendAddWorld(this);
  CObjectListItem * item = getFirst();
  while (item != NULL){
    CSrvObject * cell = (CSrvObject*)item->getObject();
    item = item->getNext();
    cell->sendObject( listener );
  }
}

void CSrvWorld::loadObjects(FILE * cellFile,CWorldObject * parent,int numObjects){
  int ii;
  for (ii = 0; ii < numObjects; ii++){
    int geometryId,numChildren;
    double posx,posy,posz;
    char objectType[256];
    char objectName[256];
    if (fscanf(cellFile,"%s %i %lf %lf %lf %s %i\n",objectType,&geometryId,&posx,&posy,&posz,objectName,&numChildren)==7){
      printf("    Obj: %s geometryId %i\n",objectType,geometryId);
      CWorldObject * object = parent->createObject(objectType,getNewObjectId(),geometryId,CPosition(posx,posy,posz),CDirection(0.0,0.0,0.0));
      parent->addObject( object );
      object->setName(objectName);
      loadObjects(cellFile,object,numChildren);
    }
  }
}


void CSrvWorld::loadWorld( char * worldFilePath ){
  char worldFileName[256];
  int cellId,numPVS;
  char cellName[256];
  char cellFileName[256];
  int pvsId;
  double posx,posy,posz;

  // Find and open world file
  sprintf(worldFileName,"%s/world",worldFilePath);
  FILE * worldFile = fopen(worldFileName,"r");
  if (worldFile == NULL) {
    printf("Failed to open file: %s\n",worldFileName);
    return;
  }

  // Read sections from world
  while (fscanf(worldFile,"%i %s %i\n",&cellId,cellName,&numPVS)==3){
    printf("  Cell: %s(%i) with %i pvs's\n",cellName,cellId,numPVS);

    // Load cell
    sprintf(cellFileName,"%s/%s",worldFilePath,cellName);
    FILE * cellFile = fopen(cellFileName,"r");
    if (cellFile != NULL){
      int geometryId,numChildren;
      char objectType[256];
      CSrvObject * cell;
      if (fscanf(cellFile,"%s %i %lf %lf %lf %i\n",objectType,&geometryId,&posx,&posy,&posz,&numChildren)==6){
        printf("    Obj: %s geometryId %i\n",objectType,geometryId);

        cell = (CSrvObject*)createObject(-1,objectType,cellId,geometryId,CPosition(0,0,0),CDirection(0,0,0));

        // Hack have to create this from input files or geometry files
        cell->setBBox(new CBBox(-250,-250,0,250,250,300));
        cell->setName(cellName);

        loadObjects(cellFile,cell,numChildren);
      }

      // Load PVS
      while ((numPVS-- > 0) && (fscanf(worldFile,"%i %lf %lf %lf\n",&pvsId,&posx,&posy,&posz)==4)){
        printf("    PVS: %i %f %f %f\n",pvsId,posx,posy,posz);
        cell->addPVCell(pvsId,CPosition(posx,posy,posz));
      }

    } else {
      printf("Failed to load cell\n");
    }

  }
  fclose(worldFile);
}