/*
  Copyright (c) 2000 Caldera Systems

  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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "monitorpageimpl.h"
#include "kxdata.h"

#include <assert.h>

#include <qlineedit.h>
#include <qheader.h>
#include <qvalidator.h>

#include <klocale.h>
#include <kdebug.h>
#include <klistview.h>
#include <knuminput.h>

MonitorPage::MonitorPage( QWidget *parent, const char *name )
    : MonitorPageBase( parent, name )
{
    m_vendors->header()->hide();

    connect( m_vendors, SIGNAL( currentChanged( QListViewItem * ) ),
             this, SIGNAL( changed() ) );

    connect( m_vendors, SIGNAL( currentChanged( QListViewItem * ) ),
             this, SLOT( vendorSelected( QListViewItem * ) ) );

    connect( m_monitors, SIGNAL( currentChanged( QListViewItem * ) ),
             this, SIGNAL( changed() ) );

    connect( m_monitors, SIGNAL( currentChanged( QListViewItem * ) ),
             this, SLOT( monitorSelected( QListViewItem * ) ) );

    connect( m_vSyncMax, SIGNAL( textChanged( const QString & ) ),
             SIGNAL( changed() ) );
    connect( m_vSyncMin, SIGNAL( textChanged( const QString & ) ),
             SIGNAL( changed() ) );
    connect( m_hSyncMax, SIGNAL( textChanged( const QString & ) ),
             SIGNAL( changed() ) );
    connect( m_hSyncMin, SIGNAL( textChanged( const QString & ) ),
             SIGNAL( changed() ) );

    connect( m_vSyncMax, SIGNAL( textChanged( const QString & ) ),
             SLOT( checkVSync() ) );
    connect( m_vSyncMin, SIGNAL( textChanged( const QString & ) ),
             SLOT( checkVSync() ) );
    connect( m_hSyncMax, SIGNAL( textChanged( const QString & ) ),
             SLOT( checkHSync() ) );
    connect( m_hSyncMin, SIGNAL( textChanged( const QString & ) ),
             SLOT( checkHSync() ) );

    QDoubleValidator *validator = new QDoubleValidator( m_hSyncMin );
    validator->setRange( 0, 200, 2 ); // ### fixme (hardcoded)
    m_hSyncMin->setValidator( validator );

    validator = new QDoubleValidator( m_hSyncMax );
    validator->setRange( 0, 200, 2 );
    m_hSyncMax->setValidator( validator );

    validator = new QDoubleValidator( m_vSyncMin );
    validator->setRange( 0, 200, 2 );
    m_vSyncMin->setValidator( validator );

    validator = new QDoubleValidator( m_vSyncMax );
    validator->setRange( 0, 200, 2 );
    m_vSyncMax->setValidator( validator );

}

MonitorPage::~MonitorPage()
{
}

void MonitorPage::load()
{
    m_current = m_data->currentMonitors()[ 0 ];

    m_vendors->clear();
    m_monitors->clear();

    KXMonitorDataMap monitors = m_data->monitors();
    KXMonitorDataMap::ConstIterator vendorIt = monitors.begin();
    KXMonitorDataMap::ConstIterator vendorEnd = monitors.end();
    for (; vendorIt != vendorEnd; ++vendorIt )
    {
        QListViewItem *vendorItem = new QListViewItem( m_vendors, 0 );
        vendorItem->setText( 0, vendorIt.key() );

        if ( vendorIt.key().lower() == m_current.vendor().lower() )
        {
            m_vendors->setCurrentItem( vendorItem );
            m_vendors->ensureItemVisible( vendorItem );
            vendorSelected( vendorItem );
        }
    }

    // Select current monitor
    QListViewItem *monitorItem = m_monitors->firstChild();
    for (; monitorItem; monitorItem = monitorItem->nextSibling() )
    {
        int size = monitorItem->text( 1 ).toInt();
        if ( monitorItem->text( 0 ).lower() == m_current.model().lower() &&
             ( m_current.size() == 0 || size == m_current.size() ) )
        {
            m_monitors->setCurrentItem( monitorItem );
            m_monitors->ensureItemVisible( monitorItem );

            displayMonitorDetails();

            enableForward( true );
            break;
        }
    }
}

void MonitorPage::save()
{
    kdDebug() << "MonitorPage::save()" << endl;

    QListViewItem *item = m_vendors->currentItem();
    if ( item )
        m_current.setVendor( m_vendor->text() );
    else
        return;

    item = m_monitors->currentItem();
    if ( item )
        m_current.setModel( m_name->text() );
    else
        return;

    m_current.setHSync( m_hSyncMin->text().toDouble(), m_hSyncMax->text().toDouble() );
    m_current.setVSync( m_vSyncMin->text().toDouble(), m_vSyncMax->text().toDouble() );

    m_data->currentMonitors()[ 0 ] = m_current;
}

void MonitorPage::monitorSelected( QListViewItem *item )
{
    assert( item );

    QListViewItem *vendorItem = m_vendors->currentItem();

    assert( vendorItem );
    assert( vendorItem->isSelected() );

//    kdDebug() << "MonitorPage::monitorSelected(): vendor: " << vendorItem->text( 0 ) << endl;

    // find vendor
    KXMonitorDataList vendorList = m_data->monitors()[ vendorItem->text( 0 ) ];

    KXMonitorDataList::ConstIterator it = vendorList.begin();
    KXMonitorDataList::ConstIterator end = vendorList.end();
    for (; it != end; ++it )
    {
        int size = item->text( 1 ).toInt();
        if ( item->text( 0 ) == (*it).model() &&
             size == (*it).size() )
        {
//            kdDebug() << "MonitorPage::monitorSelected() found" << endl;

            m_current = *it;

            displayMonitorDetails();

            emit enableForward( true );
            break;
        }
    }
}

void MonitorPage::vendorSelected( QListViewItem *item )
{
    if ( !item )
        return;

    QString vendor = item->text( 0 );

    KXMonitorDataList monitorList = m_data->monitors()[ vendor ];

    m_monitors->clear();

    KXMonitorDataList::ConstIterator it = monitorList.begin();
    KXMonitorDataList::ConstIterator end = monitorList.end();
    for (; it != end; ++it )
    {
        QListViewItem *item = new QListViewItem( m_monitors );
        item->setText( 0, (*it).model() );
        int size = (*it).size();
        if (size > 0)
            item->setText( 1, QString::number( size ) );

        clearMonitorDetails();
        emit enableForward( false );
    }
}

void MonitorPage::displayMonitorDetails()
{
    m_vendor->setText( m_current.vendor() );
    m_vendor->setEnabled( true );

    m_name->setText( m_current.model() );
    m_name->setEnabled( true );

    if (m_current.hSyncMin() == 0 )
        m_hSyncMin->setText( "" );
    else
        m_hSyncMin->setText( QString::number( m_current.hSyncMin() ) );
    m_hSyncMin->setEnabled( true );

    if (m_current.hSyncMax() == 0 )
        m_hSyncMax->setText( "" );
    else
        m_hSyncMax->setText( QString::number( m_current.hSyncMax() ) );
    m_hSyncMax->setEnabled( true );

    if (m_current.vSyncMin() == 0 )
        m_vSyncMin->setText( "" );
    else
        m_vSyncMin->setText( QString::number( m_current.vSyncMin() ) );
    m_vSyncMin->setEnabled( true );

    if (m_current.vSyncMax() == 0 )
        m_vSyncMax->setText( "" );
    else
        m_vSyncMax->setText( QString::number( m_current.vSyncMax() ) );
    m_vSyncMax->setEnabled( true );
}

void MonitorPage::clearMonitorDetails()
{
    m_vendor->setText( QString::null );
    m_vendor->setEnabled( false );

    m_name->setText( QString::null );
    m_name->setEnabled( false );

    m_hSyncMin->setText( QString::null );
    m_hSyncMin->setEnabled( false );
    m_hSyncMax->setText( QString::null );
    m_hSyncMax->setEnabled( false );

    m_vSyncMin->setText( QString::null );
    m_vSyncMin->setEnabled( false );
    m_vSyncMax->setText( QString::null );
    m_vSyncMax->setEnabled( false );
}

QString MonitorPage::quickHelp() const
{
    return i18n("<h1>Monitor Setup</h1><p>Please choose a monitor model from the list of vendors and "
                "models on the right or specify a user defined model in the input fields below.</p>");
}

void MonitorPage::checkHSync()
{
    float min = m_hSyncMin->text().toFloat();
    float max = m_hSyncMax->text().toFloat();

    // The value 200 as max frequency is only a guess
    if ( min > max || min < 0 || min > 200 || max < 0 || max > 200 )
    {
        emit enableForward( false );
        emit status( i18n( "Illegal range for horizontal sync frequency." ) );
    }
    else
    {
        emit enableForward( true );
        emit status( "" );
    }
}

void MonitorPage::checkVSync()
{
    float min = m_vSyncMin->text().toFloat();
    float max = m_vSyncMax->text().toFloat();

    if ( min > max || min < 0 || min > 200 || max < 0 || max > 200 )
    {
        emit enableForward( false );
        emit status( i18n( "Illegal range for vertical refresh rate.") );
    }
    else
    {
        emit enableForward( true );
        emit status( "" );
    }
}


#include "monitorpageimpl.moc"

