/*
 * 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 <string.h>
#include <stdlib.h>
#include "pvvmud.H"
#include "mud.H"
#include "srvclimanager.H"


CSrvCliCmdParser::CSrvCliCmdParser(CMud * mud, CClientManager * manager):
  CCommandParser()
{
  m_mud = mud;
  m_manager = manager;

  addCommand("help",(CommandFunc_t)&commandHelp);
  addCommand("create",(CommandFunc_t)&commandCreate);
  addCommand("delete",(CommandFunc_t)&commandDelete);
  addCommand("move",(CommandFunc_t)&commandMove);
  addCommand("rotate",(CommandFunc_t)&commandRotate);

}

CSrvCliCmdParser::~CSrvCliCmdParser(){
}

void CSrvCliCmdParser::commandUnknown(const string & commandString){
  m_manager->sendMsg("Unkown command!\n");
}

///////////////////////////////////////////////////////////////////////////////
// commandHelp
//   Syntax: /help [command]
///////////////////////////////////////////////////////////////////////////////
void CSrvCliCmdParser::commandHelp(argv_t & argv){
  if (argv.size() == 2){
    if (argv[1] == "help"){
      m_manager->sendMsg(
        "help [<command>]\n"
        "  Use this command to get help.\n"
      );
    } else if (argv[1] == "create"){
      m_manager->sendMsg(
        "create object <geometryId> <parentId> <pos> [<dir>]\n"
        "  Add geometry to the world.\n"
      );
    } else if (argv[1] == "delete"){
      m_manager->sendMsg(
        "delete <objectId>\n"
        "  Delete a object from the world.\n"
      );
    } else if (argv[1] == "move"){
      m_manager->sendMsg(
        "move <objectId> <position>\n"
        "  Move a object to the given position.\n"
      );
    } else if (argv[1] == "rotate"){
      m_manager->sendMsg(
        "rotate <objectId> <direction> [<time>]\n"
        "  Rotate a object to the given direction.\n"
      );
    } else {
      m_manager->sendMsg( "Unkown kommand\n" );
    }
  } else { 
    m_manager->sendMsg(
      "Help\n"
      "  Commands start with '/' everything else is chat messages\n"
      "  Commands:\n"
      "    /help\n"
      "    /create\n"
      "    /delete\n"
      "    /move\n"
      "    /rotate\n"
      "  Use /help <command> for help about a command\n"
    );
  }
}

///////////////////////////////////////////////////////////////////////////////
// commandChat
///////////////////////////////////////////////////////////////////////////////
void CSrvCliCmdParser::commandChat(const string & chatMessage){
  string msg = string("<") + m_manager->getName() + "> " + chatMessage + "\n";
  m_mud->chatMessage(msg.c_str());
}

///////////////////////////////////////////////////////////////////////////////
// commandCreate
//   Syntax: /create <objectType> <objectArgs> <parentId> <pos> [<dir>]
//   Eks   : /create object geometry/common/plants/Tree_1 cell4 20.5 23.2 0.0
///////////////////////////////////////////////////////////////////////////////
void CSrvCliCmdParser::commandCreate(argv_t & argv){

  for (int i = 0; i < argv.size(); i++){
    cout << ":" << argv[i];
  }

  cout << ":" << endl;

  if (argv.size() < 6){
    m_manager->sendMsg("Wrong arguments!\n"); 
    return;
  }

  if (argv[1] == "object"){  // Object
    char * objectType = (char*)argv[1].c_str();
    int geometryId = atoi(argv[2].c_str());
    int parentId = atoi(argv[3].c_str());
    float posx = atof(argv[4].c_str());
    float posy = atof(argv[5].c_str());
    float posz = atof(argv[6].c_str());
    float heading = 0.0,roll = 0.0,pitch = 0.0;    
    if (argv.size() >= 9){
      heading = atof(argv[7].c_str());
      roll = atof(argv[8].c_str());
      pitch = atof(argv[9].c_str());
    }
    CPosition pos = CPosition(posx,posy,posz);
    CDirection dir = CDirection(heading,roll,pitch);
    DWORD objectId = m_mud->getWorld()->getNewObjectId();
    m_mud->getWorld()->createObject(parentId,objectType,objectId,geometryId,pos,dir);
  } else {
    m_manager->sendMsg("Unknown objecType!\n"); 
  }
}

///////////////////////////////////////////////////////////////////////////////
// commandDelete
//   Syntax: /delete <objectId> 
///////////////////////////////////////////////////////////////////////////////
void CSrvCliCmdParser::commandDelete(argv_t & argv){

  if (argv.size() != 2){
    m_manager->sendMsg("Wrong number of arguments!\n"); 
    return;
  }

  int objectId = atoi(argv[1].c_str());

  CSrvObject * object = (CSrvObject*)m_mud->getWorld()->getObject(objectId);

  if (object != NULL)
    m_mud->getWorld()->removeObject(objectId,object->getParentId());
}

///////////////////////////////////////////////////////////////////////////////
// commandMove
//   Syntax: /move <objectId> <position>
///////////////////////////////////////////////////////////////////////////////
void CSrvCliCmdParser::commandMove(argv_t & argv){

  if (argv.size() != 5){
    m_manager->sendMsg("Wrong number of arguments!\n"); 
    return;
  }

  int objectId = atoi(argv[1].c_str());
  float posx = atof(argv[2].c_str());
  float posy = atof(argv[3].c_str());
  float posz = atof(argv[4].c_str());
  CPosition position = CPosition(posx,posy,posz);

  m_mud->getWorld()->updatePosition(objectId,position);
}

///////////////////////////////////////////////////////////////////////////////
// commandDelete
//   Syntax: /rotate <objectId> <direction> [<time>]
///////////////////////////////////////////////////////////////////////////////
void CSrvCliCmdParser::commandRotate(argv_t & argv){

  if (argv.size() < 5 || argv.size() > 6){
    m_manager->sendMsg("Wrong number of arguments!\n"); 
    return;
  }

  int objectId = atoi(argv[1].c_str());
  float heading = atof(argv[2].c_str());
  float roll = atof(argv[3].c_str());
  float pitch = atof(argv[4].c_str());

  if (argv.size() == 6){
    float time = atof(argv[5].c_str());
    if (time == 0.0) time = 1.0;

    CDirection angleSpeed = CDirection(heading/time,roll/time,pitch/time);

    cdebug << "Angle: " << angleSpeed << endl;

    m_mud->getWorld()->rotate(objectId,angleSpeed);
  } else {
    CDirection direction = CDirection(heading,roll,pitch);

    m_mud->getWorld()->updateDirection(objectId,direction);
  }
}