/*
 * client/ControlsMenu.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 "ControlsMenu.h"

#include "../widgets/Widget.h"
#include "../widgets/LabelWidget.h"
#include "../widgets/ScrollpaneWidget.h"
#include "../widgets/ButtonWidget.h"
#include "../widgets/TableWidget.h"
#include "../widgets/DefaultTableModel.h"
#include "../widgets/SliderWidget.h"
#include "ClientState.h"

ControlsMenu::ControlsMenu( int w, int h, Client::State escape, Client::State close )
        : GenericScreen( w, h, escape, close ) 
{
        char buf[256];

        _name = "ControlsMenu";

        _label = new LabelWidget( 256, 32, "Controls Settings" );
        _label->setOpaque( true );

        addCenter( _label,  h - _label->getHeight() );

        // setup mouse sensitivity stuff
        
        _mouseLabel = new LabelWidget( 192, 32, "Mouse Sensitivity" );
        _mouseLabel->setOpaque( true );

        add( _mouseLabel, 0, _label->getY() - _mouseLabel->getHeight() - 8 );
        
        _mouseSlider = new SliderWidget( w - 320, 32,
                                         SLIDER_HORIZONTAL,
                                         40,
                                         1,
                                         (int) ( cl_state.mouse_sensitivity * 20 ) );
        _mouseSlider->setOpaque( true );

        add( _mouseSlider, 
             _mouseLabel->getRight(), _mouseLabel->getY() );

        sprintf( buf, "%.2f", cl_state.mouse_sensitivity );
        _mouseField = new LabelWidget( 128, 32, buf );
        _mouseField->setOpaque( true );

        add( _mouseField,
             _mouseSlider->getRight(), _mouseSlider->getY() );
        
        
        // setup player walk speed stuff
        
        _walkLabel = new LabelWidget( 192, 32, "Walking Speed" );
        _walkLabel->setOpaque( true );

        add( _walkLabel, 0, _mouseLabel->getY() - _walkLabel->getHeight() - 8 );
        
        _walkSlider = new SliderWidget( w - 320, 32,
                                        SLIDER_HORIZONTAL,
                                        20,
                                        1,
                                        cl_state.walk_speed );
        _walkSlider->setOpaque( true );

        add( _walkSlider, 
             _walkLabel->getRight(), _walkLabel->getY() );

        sprintf( buf, "%d", cl_state.walk_speed );
        _walkField = new LabelWidget( 128, 32, buf );
        _walkField->setOpaque( true );
        
        add( _walkField,
             _walkSlider->getRight(), _walkSlider->getY() );

        _reverseButton = new ButtonWidget( 192, 32, "Reverse Mouse Y" );
        _reverseButton->setToggleable( true );
        _reverseButton->setSelected( cl_state.reverse_mouse_y );
        _reverseButton->addWidgetEventListener( this );

        addCenter( _reverseButton, _walkSlider->getY() - _reverseButton->getHeight() - 8 );
        
        static const char * bind_names[] = { "Action", "Key" };
        
        enum TableCellType types[] = { TABLE_CELL_CHAR_PTR, TABLE_CELL_CHAR_PTR };

        static const void * values[20][2] = {
                { "Walk Forward", "Right Mouse" },
                { "Walk Backward", "A" },
                { "Step Left",     "S" },
                { "Step Right",    "F" },
                { "Jump",          "Space or Backspace" },
                { "Automap",       "Tab" },
                { "Character Screen", "C" },
                { "Screenshot",    "F10" },
                { "Change Camera", "F9" },
                { "Screen Size",   "+/-" },
                { "Fov Up/Down",   "Q/W" },
                { "Terminate",     "F1" },
                { "Game Menu",     "ESC" },
                { "Texture Mapping", "CTRL-T" },
                { "Lightmapping",  "CTRL-L" },
                { "Dynamic Lighting", "CTRL-D" },
                { "Wireframe",     "CTRL-F" },
                { "PVS",           "CTRL-V" },
                { "Show Stats",    "CTRL-S" },
                { "Grab Input",    "CTRL-G" }
        };

        _bindingsModel = new DefaultTableModel( 20, 2,
                                                (const char **) bind_names,
                                                types,
                                                (void **) values );
        
        _bindingsTable = new TableWidget( 300, 19 * 20, _bindingsModel );

        const int widths[2] = { _bindingsTable->getSize()[0] * 3 / 5,
                                _bindingsTable->getSize()[0] * 2 / 5 };
        
        _bindingsTable->setColumnWidths( widths ); 
        
        class TableHeader * header = _bindingsTable->getHeader();
        header->setOpaque( true );

        addCenter( header, _reverseButton->getY() - header->getHeight() - 16 );

        _bindingsScroll = new ScrollpaneWidget( header->getWidth(), header->getY() - 100, _bindingsTable );
        _bindingsScroll->scrollTo( 0, _bindingsTable->getHeight() );

        addCenter( _bindingsScroll, 100 );
        
        _backButton = new ButtonWidget( 128, 32, "Back" );
        _backButton->setOpaque( true );

        addCenter( _backButton, 16 );

        _walkSlider->addWidgetEventListener( this );
        _mouseSlider->addWidgetEventListener( this );
        _backButton->addWidgetEventListener( this );
        acceptEventType( EVENT_ACTION, true );
        
}

ControlsMenu::~ControlsMenu() {
}

void ControlsMenu::handleEvent( const class WidgetEvent * evt ) {

        char buf[128];
        
        if ( evt->getSource() == _mouseSlider ) {
                cl_state.mouse_sensitivity = 0.05F * _mouseSlider->getValue();
                sprintf( buf, "%.2f", cl_state.mouse_sensitivity );
                
                _mouseField->setText( buf );
        }

        else if ( evt->getSource() == _walkSlider ) {
                cl_state.walk_speed = _walkSlider->getValue();
                sprintf( buf, "%d", cl_state.walk_speed );
                
                _walkField->setText( buf );
        }
        else if ( evt->getSource() == _backButton ) {
                doEscapeAction();
        }
        
        else if ( evt->getSource() == _reverseButton ) {
                cl_state.reverse_mouse_y = ! cl_state.reverse_mouse_y;
        }
}
