/*
 * widgets/ConsoleWidget.cc:
 *
 * Copyright (C) 2000 John Watson, jwatson@tempusmud.com
 * 
 * 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 "WidgetEvents.h"
#include "Widget.h"
#include "ConsoleWidget.h"

#include "TextPaneWidget.h"
#include "TextFieldWidget.h"
#include "ScrollpaneWidget.h"
#include "../util/TextureFont.h"

void ConsoleWidget::paint() 
{
        Widget::paint();
}

ConsoleWidget::ConsoleWidget( int w, int h ) : Widget( w, h ) {

        int texheight = _font->getFontHeight();

        texheight = max( 20, texheight + 4 );

        _inputField = new TextFieldWidget( w, texheight );
        
        acceptEventType( EVENT_ACTION, true );
        
        _inputField->addWidgetEventListener( this );

        _textPane = new TextPaneWidget( w - 16, h - texheight );
        
        _textPane->setKeyEventHijacker( _inputField );
        
        _scrollpane = new ScrollpaneWidget( w, 
                                            h - texheight,
                                            _textPane,
                                            SCROLLBAR_NEVER,
                                            SCROLLBAR_ALWAYS,
                                            16,
                                            16 );

        _curHistoryIndex = -1;
        
        add( _scrollpane, 0, texheight );
        add( _inputField, 0, 0 );
}

ConsoleWidget::~ConsoleWidget() {
        _textPane->setKeyEventHijacker( 0 );
        _inputField->removeWidgetEventListener( this );
        delete _inputField;
        delete _textPane;
        delete _scrollpane;
}

static const char * getListElem( list< const char *> l, int index ) {

        list< const char *>::const_iterator end = l.end();
        int num = 0;

        for ( list<const char *>::const_iterator iter = l.begin();
              iter != end;
              ++iter, ++num ) {
                if ( num == index )
                        return *iter;
        }

        return 0;
}

void ConsoleWidget::handleEvent( const class WidgetEvent *evt ) {
        
        if ( evt->getType() == EVENT_ACTION ) {
                class ActionEvent * a_evt = (ActionEvent *) evt;
                
                const char *command = a_evt->getActionCommand();

                //
                // scroll up through history
                //

                if ( ! strcasecmp( command, TextFieldWidget::HISTORY_RECALL_UP_COMMAND ) ) {
                        if ( ( _curHistoryIndex + 1 ) < (int) _history.size() ) {

                                if ( _curHistoryIndex == -1 ) {
                                        strcpy( _curCommandLine, _inputField->getText() );
                                }
                                
                                ++_curHistoryIndex;

                                const char * s = getListElem( _history, _curHistoryIndex );

                                if ( s == 0 ) {
                                        cout << " ERROR in ConsoleWidget::handleEvent UP" << endl;
                                        return;
                                }

                                
                                _inputField->setText( s );
                        }
                        else {
                                cout << " TODO: beep" << endl;
                        }
                        
                        return;

                }

                //
                // scroll down through history
                //

                else if ( ! strcasecmp( command, TextFieldWidget::HISTORY_RECALL_DOWN_COMMAND ) ) {
                        
                        if ( _curHistoryIndex >= 0 ) {
                                --_curHistoryIndex;

                                const char * s = 0;
                                
                                if ( _curHistoryIndex == -1 ) {
                                        s = _curCommandLine;
                                }
                                
                                else {
                                        
                                        s = getListElem( _history, _curHistoryIndex );
                                        
                                        if ( s == 0 ) {
                                                cout << " ERROR in ConsoleWidget::handleEvent DOWN" << endl;
                                                return;
                                        }
                                }

                                _inputField->setText( s );
                                
                        }
                        else {
                                cout << " TODO: beep" << endl;
                        }
                        
                        return;   
                }

                cout << " CONSOLE appending " << command << endl;

                _textPane->appendLine( command );

                _curHistoryIndex = -1;

                pushHistory( command );

                if ( ! strcasecmp( command, "history" ) ) {
                        
                        int cur_num = _history.size();
                        char buf[ MAX_HISTORY_ELEMENT_LEN + 16 ];

                        list< const char * >::reverse_iterator end = _history.rend();
                        for ( list< const char * >::reverse_iterator iter = _history.rbegin();
                              iter != end;
                              ++iter ) {
                                sprintf( buf, " %2d ] %s", --cur_num, *iter );
                                _textPane->appendLine( buf );
                        }
                }
        }
}

void ConsoleWidget::pushHistory( const char * str ) {

        if ( _history.size() >= MAX_HISTORY_SIZE ) {
                const char * oldstr = _history.back();
                _history.pop_back();
                delete[] oldstr;
        }
        
        char * str_ptr = new char[ MAX_HISTORY_ELEMENT_LEN ];
        
        strncpy( str_ptr, str, MAX_HISTORY_ELEMENT_LEN - 1 );
        str_ptr[ MAX_HISTORY_ELEMENT_LEN - 1 ] = 0;

        _history.push_front( str_ptr );
}

bool ConsoleWidget::keyPressed( SDL_KeyboardEvent * evt, int x, int y ) { 
        
        if ( evt->keysym.sym == SDLK_PAGEUP || evt->keysym.sym == SDLK_PAGEDOWN ) {
                if ( _scrollpane->keyPressed( evt, 0, 0 ) )
                        return true;
        }

        return Widget::keyPressed( evt, x, y );
}
