/**********************************************************************************************
    Copyright (C) 2009 Oliver Eichler oliver.eichler@gmx.de

    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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

**********************************************************************************************/

#include "CBacklight.h"
#include "CCanvas.h"

#include <QtGui>

CBacklight * CBacklight::m_self = 0;

#define CLASS_BACKLIGHT "/sys/class/backlight/"
#define CLASS_LCD       "/sys/class/lcd/"


CBacklight::CBacklight(QObject * parent)
: QObject(parent)
, maxBrightness(100)
, actBrightness(10)
, oldBrightness(10)
, timeout(-1)
, noService(false)
{
    m_self = this;

    QStringList dirs;

    dirs = QDir(CLASS_BACKLIGHT).entryList();
    if(dirs.count() < 3){
        qWarning("Failed to retrieve " CLASS_BACKLIGHT);
        noService = true;
    }
    else{
        QString szPath( CLASS_BACKLIGHT );
        szPath.append( dirs.at(2).toLocal8Bit().constData() );
        szPath.append( "/" );
        dirDeviceBacklight.setPath( szPath );

    }

    dirs = QDir(CLASS_LCD).entryList();
    if(dirs.count() < 3){
        qWarning("Failed to retrieve " CLASS_LCD);
        noService = true;
    }
    else{
        QString szPath( CLASS_LCD );
        szPath.append( dirs.at(2).toLocal8Bit().constData() );
        szPath.append( "/" );
        dirDeviceLcd.setPath( szPath );

    }

    if(!noService){
        QString line;
        QFile  file;
        // read maximum brightness
        file.setFileName(dirDeviceBacklight.absoluteFilePath("max_brightness"));
        file.open( QIODevice::ReadOnly | QIODevice::Text);
        line = file.readLine();
        maxBrightness = (line.toInt() / 10) *10;
        file.close();
        qDebug() << "cat " << dirDeviceBacklight.absoluteFilePath("max_brightness") << maxBrightness;
    }
    for(int i = 0; i < 11; ++i){
        levels[i] = i * maxBrightness / 10;
    }


    // restore last brightness value
    QSettings cfg;
    int level = cfg.value("lcd/brightness", 1).toInt();
    setBrightness(level);

    timer = new QTimer(this);
    timer->setSingleShot(true);
    connect(timer, SIGNAL(timeout()), this, SLOT(slotTimeout()));

    setTimeout(cfg.value("lcd/timeout", timeout).toInt());

    timerFalseTrigger = new QTimer(this);
    timerFalseTrigger->setSingleShot(true);

    qApp->installEventFilter(this);
}

CBacklight::~CBacklight()
{
    QSettings cfg;
    if(actBrightness){
        cfg.setValue("lcd/brightness",brightness2level(actBrightness));
    }
    else{
        cfg.setValue("lcd/brightness",brightness2level(oldBrightness));
    }

}

void CBacklight::setBrightness(int level)
{
    QString line;
    QFile  file;

    level = level2brightness(level);
    qDebug() << "slotBrightness" << level;

    if(noService){
        actBrightness = level2brightness(level);
        CCanvas::self().lock(actBrightness == 0);
        return;
    }


    if(actBrightness < 1 && level > 0){
        line = QString("echo 4 > %1").arg(dirDeviceLcd.absoluteFilePath("power"));
        qDebug() << line.toLocal8Bit();
        system(line.toLocal8Bit());

        line = QString("echo 0 > %1").arg(dirDeviceLcd.absoluteFilePath("power"));
        qDebug() << line.toLocal8Bit();
        system(line.toLocal8Bit());

        line = QString("echo %1 > %2").arg(maxBrightness).arg(dirDeviceBacklight.absoluteFilePath("brightness"));
        qDebug() << line.toLocal8Bit();
        system(line.toLocal8Bit());
    }

    line = QString("echo %1 > %2").arg(level).arg(dirDeviceBacklight.absoluteFilePath("brightness"));
    qDebug() << line.toLocal8Bit();
    system(line.toLocal8Bit());

    if(level < 1){
        line = QString("echo 4 > %1").arg(dirDeviceLcd.absoluteFilePath("power"));
        qDebug() << line.toLocal8Bit();
        system(line.toLocal8Bit());
    }

    // read back brightness
    file.setFileName(dirDeviceBacklight.absoluteFilePath("actual_brightness"));
    file.open( QIODevice::ReadOnly | QIODevice::Text);
    line = file.readLine();
    actBrightness = line.toInt();
    file.close();

    CCanvas::self().lock(actBrightness == 0);
    qDebug() << "cat " << dirDeviceBacklight.absoluteFilePath("actual_brightness") << actBrightness;
}

int CBacklight::getBrightness()
{
    return brightness2level(actBrightness);
}

void CBacklight::toggle()
{
    if(timerFalseTrigger->isActive()){
        return;
    }

    timerFalseTrigger->start(1000);

    // in timout mode, reset the timeout
    if(actBrightness && (timeout != -1)){
        resetTimeout();
    }
    // in manual mode turn off the lcd if lcd is on
    else if(actBrightness){
        oldBrightness = actBrightness;
        setBrightness(0);
    }
    // in manual mode turn on the lcd if lcd is off
    else{
        setBrightness(brightness2level(oldBrightness));
        resetTimeout();
    }
}

void CBacklight::setTimeout(int t)
{
    timeout = t;
    resetTimeout();

    QSettings cfg;
    cfg.setValue("lcd/timeout", timeout);
}

int CBacklight::getTimeout()
{
    return timeout;
}

int CBacklight::getTimer()
{
    return timeout < (time.elapsed() / 1000) ? timeout : (time.elapsed() / 1000);;
}


void CBacklight::resetTimeout()
{
    if(timeout != -1){
        timer->start(timeout * 1000);
        time.start();
    }
    else{
        timer->stop();
    }
}

void CBacklight::slotTimeout()
{
    qDebug() << "-------------------------";
    timer->stop();
    oldBrightness = actBrightness;
    setBrightness(0);
}

bool CBacklight::eventFilter(QObject *obj, QEvent *ev)
{


    if (ev->type() == QEvent::MouseButtonPress){
        if(getTimeout() != -1){
            bool res = actBrightness == 0;
#ifdef NO_BACKLIGHT_VIA_TS
            if(!res)
#endif
            {
                toggle();
            }
            return res;
        }
    }


    if (ev->type() == QEvent::KeyPress){
        if(getTimeout() != -1 && actBrightness != 0){
            toggle();
        }
    }

    return QObject::eventFilter(obj, ev);
}
