/*
 * 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 <iostream.h>
#include <malloc.h>
#include <string.h>
#include "pvvmud.H"
#include "console.H"
#include "pvvmudclient.H"

CConsole::CConsole(CPvvmudClient * cli) {
  CConsole(cli, 40, 20);
}

CConsole::CConsole(CPvvmudClient * cli, int rows, int cols) {
  m_client = cli;
  m_cols = cols;
  m_rows = rows;
  m_print_x = m_print_y = 0;
  m_visible = FALSE;
  m_state = FALSE;
  m_echo = TRUE;
  m_dataReady = FALSE;
  //  Calculate start point for drawing (assumes 8-by-13 font)
  int cons_width = 8 * rows;
  int cons_height = 13 * cols;
  m_screen_x = (getClient()->getGUI()->getWidth() - cons_width) / 2;
  m_screen_y = getClient()->getGUI()->getHeight() - (getClient()->getGUI()->getHeight() - cons_height) / 2;
  m_input_x = 0;
  m_input_y = m_cols - 1;
  m_charColor = (double*)malloc(sizeof(double) * 3);
  m_numInputChars = 0;
  m_bufStart = 0;
    //  Allocate space for console data (one extra char for newline)
  m_console =(char*)malloc(sizeof(char) * (m_cols+1)*m_rows); 
  memset(m_console, 0, (m_cols+1)*m_rows);
} // CConsole()

CConsole::~CConsole() {
  free(m_console);
  free(m_charColor);
}

void CConsole::drawText() {
}

void CConsole::addMsg(char * msg) {
}

int CConsole::printLine(char * string) {
  int i = print(string);
  if (i) {
    //  Add newline    
    m_console[m_print_y*m_rows+m_print_x] = '\n';
    if (m_print_y < m_cols) {
      m_print_y++;
      m_print_x = 0;
    } // if
    else {
      m_print_y = m_print_x = 0;  //Reached end of console, return to top.
    } // else
  } // if
  return i;
} // printLine()

int CConsole::print(char * string) {
  char c;
  int i = 0;
  while ((c=string[i++])) {  
    if (m_print_y >= m_cols-2) {
      scroll(1);
      m_print_y--;
    }
    if (m_print_x == m_rows-1) { // Check if the cursor is at the end of a line
      m_console[m_print_y*m_rows+m_print_x] = '\n';
      if (m_print_y >= (m_cols-2)) { //  check if the cursor is at the bottom
	scroll(1);
	m_print_x = 0;
	m_print_y--;
      } // if
      else {
	m_print_y++;
	m_print_x = 0;
      } // else
      i--;
    } // if
    else if (m_print_x < m_rows) {
      m_console[m_print_y*m_rows+m_print_x] = c;
      m_print_x++;
    } // else if
    else { //  m_print> m_rows => error condition (never supposed to happen)
      return 0;
    }
    if (c == '\n') {
      m_console[m_print_y*m_rows+m_print_x] = '\n';
      m_print_y++;
      m_print_x = 0;
    } // if
  } // while
  return 1;
}

int CConsole::printChar(char c) {
  char * tmp = (char*)malloc(sizeof(char)*2);
  tmp[0] = c;
  tmp[1] = 0;
  print(tmp);
  free(tmp);
}

void CConsole::echoChar(char c) {
  if (m_input_x < m_rows) {
    m_console[m_input_y * m_rows + m_input_x] = c;
    m_input_x++;
  }
}

void CConsole::clear() {
  memset(m_console, 0, getRows()*(getCols()+1));
  setCursorPos(0, 0);
}    

void CConsole::scroll(int lines) {
  for (int i=lines;i<m_cols;i++) {
    memcpy(&m_console[(i-lines)*(m_rows)], &m_console[i*(m_rows)], m_rows+1);
  }
}
    
void CConsole::keyboardInput(char k) {
  switch (k) {
  case '\r':
    changeInputMode();
    if (m_inputBuffer != "") {
      setDataReady();
    }
    break;
  case '\b':
    if (m_numInputChars != 0) {
      m_numInputChars--;
      m_input_x--;
      m_console[m_input_y * m_rows + m_input_x] = 0;
    }
    break;
  default:    
    if (m_echo) {
      echoChar(k);
    }
    m_inputBuffer += k;
  }
}


const char * CConsole::getLine() {  
  if (getDataReady()) {
    const char * s = m_inputBuffer.c_str();
    cout << s << '\n';
    m_inputBuffer = "";
    setDataReady(FALSE);
    return s;
  }
  else {
    return NULL; //  No data ready
  }
}

/*char CConsole::getChar() {
  if (m_numInputChars) {
    char c = m_inputBuffer[m_bufStart++];
    if (m_bufStart >= INPUTSIZE) { 
      m_bufStart = 0;
      m_numInputChars--;
    } // if   
  } // if
} // getChar()*/

void CConsole::setCursorPos(int x, int y) {
  m_print_x = x;
  m_print_y = y;
}

int CConsole::getRows() {
  return m_rows;
}

int CConsole::getCols() {
  return m_cols;
}

double * CConsole::getColor() {
  return m_charColor;
}

void CConsole::setColor(double red, double green, double blue) {
  m_charColor[0] = red;
  m_charColor[1] = green;
  m_charColor[2] = blue;
}

CPvvmudClient * CConsole::getClient() {
  return m_client;
}

int CConsole::changeInputMode() {
  if(m_state) 
    m_state = 0;
  else {
    m_visible = TRUE;
    m_state = 1;
    m_input_x = 0;
    m_input_y = m_cols - 1;
  } // else
  for(int i=0;i<getRows();i++) {
    m_console[m_input_y*getRows()+i]=0;
  }
  return 0;
} 

int CConsole::getInputMode() {
  return m_state;
}

int CConsole::setVisible() {
  m_visible = (m_visible) ? 0 : 1;
  return 0;
}

int CConsole::isVisible() {
  return m_visible;
}

void CConsole::setEcho(BOOL e) {
  m_echo = e;
}

BOOL CConsole::getEcho() {
  return m_echo;
}

void CConsole::setDataReady(BOOL d) {
  m_dataReady = d;
}

BOOL CConsole::getDataReady() {
  return m_dataReady;
}