/*
 * 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 "client.H"
#include "inputfunction.H"
#include "msgsrvcli.H"
#include "srvcliconsole.H"
//  Commandline for creating default map
//  grep addInp inputfunction.C  | tr '"' ' ' | awk '{print  $4 "                  " $2}' > .pvvmud_ifm
//
//


CInputFunction::CInputFunction(CCliSrvManager * manager, CRenderer * renderer){

  m_manager = manager;
  m_renderer = renderer;

  addInputFunction("key_H","playermove_runleft",
                   (InputFunction_t)&playerMove,PLAYERMOVE_RUNLEFT); 
  addInputFunction("key_J","playermove_runbackward",
                   (InputFunction_t)&playerMove,PLAYERMOVE_RUNBACKWARD); 
  addInputFunction("key_K","playermove_runforward",
                   (InputFunction_t)&playerMove,PLAYERMOVE_RUNFORWARD); 
  addInputFunction("key_L","playermove_runright",
                   (InputFunction_t)&playerMove,PLAYERMOVE_RUNRIGHT); 

  addInputFunction("","playermove_moveleft",
                   (InputFunction_t)&playerMove,PLAYERMOVE_MOVELEFT); 
  addInputFunction("","playermove_movebackward",
                   (InputFunction_t)&playerMove,PLAYERMOVE_MOVEBACKWARD); 
  addInputFunction("","playermove_moveforward",
                   (InputFunction_t)&playerMove,PLAYERMOVE_MOVEFORWARD); 
  addInputFunction("","playermove_moveright",
                   (InputFunction_t)&playerMove,PLAYERMOVE_MOVERIGHT); 

  addInputFunction("key_h","playermove_stepleft",
                   (InputFunction_t)&playerMove,PLAYERMOVE_STEPLEFT); 
  addInputFunction("key_j","playermove_stepbackward",
                   (InputFunction_t)&playerMove,PLAYERMOVE_STEPBACKWARD); 
  addInputFunction("key_k","playermove_stepforward",
                   (InputFunction_t)&playerMove,PLAYERMOVE_STEPFORWARD); 
  addInputFunction("key_l","playermove_stepright",
                   (InputFunction_t)&playerMove,PLAYERMOVE_STEPRIGHT); 

  addInputFunction("key_0","usercommand_0",
                   (InputFunction_t)&userCommand,USERCOMMAND_0); 
  addInputFunction("key_1","usercommand_1",
                   (InputFunction_t)&userCommand,USERCOMMAND_1); 
  addInputFunction("key_2","usercommand_2",
                   (InputFunction_t)&userCommand,USERCOMMAND_2); 
  addInputFunction("key_3","usercommand_3",
                   (InputFunction_t)&userCommand,USERCOMMAND_3); 
  addInputFunction("key_4","usercommand_4",
                   (InputFunction_t)&userCommand,USERCOMMAND_4); 
  addInputFunction("key_5","usercommand_5",
                   (InputFunction_t)&userCommand,USERCOMMAND_5); 
  addInputFunction("key_6","usercommand_6",
                   (InputFunction_t)&userCommand,USERCOMMAND_6); 
  addInputFunction("key_7","usercommand_7",
                   (InputFunction_t)&userCommand,USERCOMMAND_7); 
  addInputFunction("key_8","usercommand_8",
                   (InputFunction_t)&userCommand,USERCOMMAND_8); 
  addInputFunction("key_9","usercommand_9",
                   (InputFunction_t)&userCommand,USERCOMMAND_9); 

  addInputFunction("key_escape","quit",
                   (InputFunction_t)&quitFunction,-1); 

  addInputFunction("key_space","playerlook_default",
                   (InputFunction_t)&playerlook,PLAYERLOOK_DEFAULT); 

  addInputFunction("key_enter", "toggle_inputmode",
		   (InputFunction_t)&consoleFunction, TOGGLE_CONSOLE_MODE);

  addInputFunction("key_tab", "show_hide_console",
		   (InputFunction_t)&consoleFunction, CONSOLE_SHOW_HIDE);

  addInputFunction("key_up","playerlook_forward",
                   (InputFunction_t)&playerlook,PLAYERLOOK_FORWARD); 
  addInputFunction("key_down","playerlook_backward",
                   (InputFunction_t)&playerlook,PLAYERLOOK_BACKWARD); 
  addInputFunction("key_left","playerlook_left",
                   (InputFunction_t)&playerlook,PLAYERLOOK_LEFT); 
  addInputFunction("key_right","playerlook_right",
                   (InputFunction_t)&playerlook,PLAYERLOOK_RIGHT); 
  addInputFunction("key_page_up","playerlook_up",
                   (InputFunction_t)&playerlook,PLAYERLOOK_UP); 
  addInputFunction("key_page_down","playerlook_down",
                   (InputFunction_t)&playerlook,PLAYERLOOK_DOWN); 

  addInputFunction("mouse_left_up","pick",
                   (InputFunction_t)&pickFunction,-1); 

  addInputFunction("key_d","dump",
                   (InputFunction_t)&dumpFunc,DUMP_WORLD); 
  addInputFunction("key_c","capture",
                   (InputFunction_t)&dumpFunc,DUMP_SCREEN); 

  loadMap(".pvvmud_ifm");
}

void CInputFunction::setRenderer(CRenderer * renderer) {
  m_renderer = renderer;
}

CRenderer * CInputFunction::getRenderer() {
  return m_renderer;
}

void CInputFunction::setConsole(CConsole * console) {
  m_console = console;
}

CConsole * CInputFunction::getConsole() {
  return m_console;
}

void CInputFunction::processHits(int hits, unsigned int buffer[]){
  int i;
  unsigned int selection, zvalue;
  unsigned int names,z2,z1,*ptr,j;
  cdebug << "hits = " << hits;
 
  selection = 0; zvalue = 0xFFFFFFFF; 

  ptr =  buffer;
  for (i = 0; i < hits; i++){
    names = *ptr; ptr++;
    z1 = *ptr; ptr++;
    z2 = *ptr; ptr++;
    if (z2 < zvalue){
      selection = *ptr;
      zvalue = z2;
    }
    for (j=0; j < names; j++){
      cdebug << ptr;
      ptr++;
    }
  }
  cdebug << "Selection = " << selection << "\n";
  m_manager->selection(selection);
}


int CInputFunction::playerlook(int argument){
  m_manager->playerLook(argument);
  return 0;
}

int CInputFunction::playerMove(int argument){
  m_manager->playerMove(argument);
  return 0;
}

int CInputFunction::userCommand(int argument){
  m_manager->userCommand(argument);
  return 0;
}

int CInputFunction::quitFunction(int argument){
  
  CSrvCliConsole * c = (CSrvCliConsole *)getConsole();
  c->saveHistory();
  // save_params();
  m_manager->quit();
  return 0;
}

int CInputFunction::consoleFunction(int argument) {
  switch (argument) {
  case TOGGLE_CONSOLE_MODE:
    cout << "Input" << getConsole()->getInputMode() << " -> ";
    getConsole()->changeInputMode();
    cout << getConsole()->getInputMode() << '\n';
    break;
  case CONSOLE_SHOW_HIDE:
    cout << "Visible" << getConsole()->isVisible() << " -> ";
    getConsole()->setVisible();
    cout << getConsole()->isVisible() << '\n';
    break;
  default:
    cout << "Error\n";
  }
  
  return 0;
}

int CInputFunction::pickFunction(int argument){
  m_renderer->mousePick(m_xx, m_yy);
  return 0;
}

int CInputFunction::dumpFunc(int argument){
  switch (argument){
  case DUMP_WORLD:
    m_manager->dump();
    break;
  case DUMP_SCREEN:
    m_renderer->dumpScreen("pvvmudscreen.tex");
    break;
  }
  return 0;
}


void CInputFunction::key(unsigned char k, int x, int y){
  m_xx = x; m_yy = y; // Save position i global variables
  if (getConsole()->getInputMode()) {
    getConsole()->keyboardInput(k);    
  }
  else {
    switch (k){
    case ' ':
      executeFunction("key_space");
      break;
    case 27:  /* Escape */
      executeFunction("key_escape");
      break;
    case '\r':
      executeFunction("key_enter");
      break;
    case '\t':
      executeFunction("key_tab");
      break;
    default:
      char keybuf[6];
      strcpy(keybuf,"key_?");
      keybuf[4] = k;
      executeFunction(keybuf);
    }
  }
    glutPostRedisplay();
}

void CInputFunction::special(int k, int x, int y) {
  m_xx = x; m_yy = y; // Save position i global variables
  if (getConsole()->getInputMode()) {
    switch (k) {
    case GLUT_KEY_UP:
      getConsole()->keyboardInput(KEY_UP);
      break;
    case GLUT_KEY_DOWN:
      getConsole()->keyboardInput(KEY_DOWN);
      break;
    } // swich
  } // if
  switch (k) {
  case GLUT_KEY_UP:
    executeFunction("key_up");
    break;
  case GLUT_KEY_DOWN:
    executeFunction("key_down");
    break;
  case GLUT_KEY_LEFT:
    executeFunction("key_left");
    break;
  case GLUT_KEY_RIGHT:
    executeFunction("key_right");
    break;
  case GLUT_KEY_PAGE_UP:
    executeFunction("key_page_up");
    break;
  case GLUT_KEY_PAGE_DOWN:
    executeFunction("key_page_down");
    break; 
  default:
    return;
  }
  glutPostRedisplay();
}

void CInputFunction::mouse(int button, int state, int x, int y){
  m_xx = x; m_yy = y; // Save position i global variables
  switch(button){
  case GLUT_LEFT_BUTTON:
    if (state == GLUT_UP)
      executeFunction("mouse_left_up");
    else
      executeFunction("mouse_left_down");
    break;
  case GLUT_MIDDLE_BUTTON:
    if (state == GLUT_UP)
      executeFunction("mouse_middle_up");
    else
      executeFunction("mouse_middle_down");
    break;
  case GLUT_RIGHT_BUTTON:
    if (state == GLUT_UP)
      executeFunction("mouse_right_up");
    else
      executeFunction("mouse_right_down");
    break;
  }
}