/***************************************************************************
 *   Copyright (C) 2005 by Lorenzo Bettini                                 *
 *   http://www.lorenzobettini.it                                          *
 *                                                                         *
 *   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 "brightnesschooserimpl.h"

#include <tqprocess.h>
#include <tqslider.h>
#include <tqlabel.h>
#include <tqmessagebox.h>
#include <kdebug.h>
#include <tqevent.h>
#include <tqregexp.h>

#include "preferences.h"

BrightnessChooserImpl::BrightnessChooserImpl(TQWidget *parent, const char *name)
 : BrightnessChooser(parent, name), proc(0)
{
    updateSlider();

    // check whether to restore the previous brightness value
    if (Preferences::saveCurrent()) {
        kdDebug() << "restore previous brightness value: " <<
                Preferences::currentValue() << endl;
        setValue(Preferences::currentValue());
    }

    valueLabel->setText(getValue());
    brightnessSlider->setFocus();
}


BrightnessChooserImpl::~BrightnessChooserImpl()
{
    // in case save the current brightness setting
    if (Preferences::saveCurrent()) {
        const TQString &val = getValue();
        kdDebug() << "save the current brightness value: " << val << endl;
        Preferences::setCurrentValue(val);
        Preferences::writeConfig();
    }
}

void BrightnessChooserImpl::updateSlider()
{
    brightnessSlider->setPageStep(TQString(Preferences::step()).toInt());
    brightnessSlider->setLineStep(TQString(Preferences::step()).toInt());
    brightnessSlider->setRange(TQString(Preferences::minValue()).toInt(),
                               TQString(Preferences::maxValue()).toInt()+1);
    valueLabel->setText(getValue());
    kdDebug() << "updateSlider" << endl;
    kdDebug() << "program: " << Preferences::program() << endl;
    kdDebug() << "min value: " << Preferences::minValue() << endl;
    kdDebug() << "max value: " << Preferences::maxValue() << endl;
    kdDebug() << "page step: " << brightnessSlider->pageStep() << endl;
    kdDebug() << "line step: " << brightnessSlider->lineStep() << endl;
}

void BrightnessChooserImpl::updateBrightness()
{
    if (proc)
        delete proc; // delete the previous instance

    proc = new TQProcess(this);

    TQString args = Preferences::setArgument();
    args += getValue();
    proc->addArgument( Preferences::program() );
    proc->addArgument( args );

    connect( proc, TQ_SIGNAL(readyReadStdout()),
             this, TQ_SLOT(readFromStdout()) );
    connect( proc, TQ_SIGNAL(readyReadStderr()),
             this, TQ_SLOT(readFromStderr()) );
    connect( proc, TQ_SIGNAL(processExited()),
             this, TQ_SLOT(procExited()) );

    if ( !proc->start() ) {
        // error handling
        TQMessageBox::critical( 0,
                               tr("Fatal error"),
                               tr("Could not start the brightness adjustment command."),
                               tr("Quit") );
    }

    TQString arguments = proc->arguments().join(" ");
    tqWarning("%s", arguments.ascii());
}

void BrightnessChooserImpl::getBrightness()
{
    TQString args = Preferences::getArgument();

    /* some programs, such as nvclock, do not have a parameter to
    get the current brightness; in such case we simply return */
    if (args == "") {
        kdDebug() << "the program does not support a get brightness functionality" << endl;
        return;
    }

    if (proc)
        delete proc; // delete the previous instance

    proc = new TQProcess(this);

    proc->addArgument( Preferences::program() );
    proc->addArgument( args );

    connect( proc, TQ_SIGNAL(readyReadStdout()),
             this, TQ_SLOT(readValueFromStdout()) );
    connect( proc, TQ_SIGNAL(readyReadStderr()),
             this, TQ_SLOT(readFromStderr()) );
    connect( proc, TQ_SIGNAL(processExited()),
             this, TQ_SLOT(procExited()) );

    if ( !proc->start() ) {
        // error handling
        TQMessageBox::critical( 0,
                               tr("Fatal error"),
                               tr("Could not start the brightness adjustment command."),
                               tr("Quit") );
    }

    TQString arguments = proc->arguments().join(" ");
    tqWarning("%s", arguments.ascii());
}

void BrightnessChooserImpl::updateValue(int)
{
    valueLabel->setText(getValue());
}

void BrightnessChooserImpl::readFromStderr()
{
    // Read and process the data.
    // Bear in mind that the data might be output in chunks.
    TQString out = proc->readStderr();
    tqWarning( "%s", out.ascii() );
}

void BrightnessChooserImpl::readFromStdout()
{
    // Read and process the data.
    // Bear in mind that the data might be output in chunks.
    TQString out = proc->readStdout();
    tqWarning( "%s", out.ascii() );
}

void BrightnessChooserImpl::readValueFromStdout()
{
    // Read and process the data.
    // Bear in mind that the data might be output in chunks.
    TQString out = proc->readStdout();
    TQRegExp regexp("(\\d+)");
    if (regexp.search(out) > 0) {
        TQString result = regexp.cap(1);
        kdDebug() << "initial slider value: " << brightnessSlider->value() << endl;
        kdDebug() << "captured result: " << result << endl;
        brightnessSlider->setValue(brightnessSlider->maxValue() - result.toInt());
        kdDebug() << "updated slider value: " << brightnessSlider->value() << endl;
    }
    tqWarning( "%s", out.ascii() );
}

void BrightnessChooserImpl::procExited()
{
    tqWarning("process terminated");

    emit valueUpdated();
}

const TQString BrightnessChooserImpl::getValue()
{
    return TQString::number((brightnessSlider->maxValue() - brightnessSlider->value()));
}

void BrightnessChooserImpl::setValue(const TQString &val)
{
    int iVal = brightnessSlider->maxValue() - val.toInt();
    kdDebug() << "set slider value: " << iVal << endl;
    brightnessSlider->setValue(iVal);
    updateBrightness();
}

void BrightnessChooserImpl::keyPressEvent(TQKeyEvent *event)
{
    /* intercept ENTER and simulate the OK button;
     also intercept ESC in order to close the parent widget (otherwise
     ESC is passed to the applet which seems to close the main panel?)*/
    if (event->key() == TQt::Key_Return || event->key() == TQt::Key_Enter) {
        kdDebug() << "pressed ENTER" << endl;
        updateBrightness();
    } else if (event->key() == TQt::Key_Escape) {
        kdDebug() << "pressed ESC" << endl;
        parentWidget()->close();
    } else {
        BrightnessChooser::keyPressEvent(event);
    }
}

#include "brightnesschooserimpl.moc"
