/*
 *  SynDaemon.cpp
 *
 *  Copyright (C) 2007, 2008  Stefan Kombrink
 *
 *  This file is part of TouchFreeze.
 *
 *  TouchFreeze 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 3 of the License, or
 *  (at your option) any later version.
 *
 *  TouchFreeze 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 touchfreeze; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 *
 *  On Debian GNU/Linux systems, the complete text of the GNU General
 *  Public License can be found in the /usr/share/common-licenses/GPL file.
 */


#include "SynDaemon.h"
#include <QSettings>

SynDaemon::SynDaemon( QObject* parent ) : QObject( parent )
{
    qDebug() << "SynDaemon::SynDaemon" << endl;

    mBypassTimer.setSingleShot( true );
    connect( &mBypassTimer, SIGNAL( timeout() ), this, SLOT( onStopTyping() ) );
    connect( this, SIGNAL( triggerBypass() ), this, SLOT( onStartTyping() ) );

    // use last saved values    
    rollbackSettings();
    
    mDisplay = NULL;
    mDisplay = XOpenDisplay( NULL );

    mPollingTimer.setInterval( 20 );
    connect( &mPollingTimer, SIGNAL( timeout() ), this, SLOT( checkOnKeyboardActivity() ) );
    
    mPollingTimer.start();
}

void SynDaemon::checkOnKeyboardActivity()
{
    if ( hasKeyboardActivity() )
        emit triggerBypass();
}

void SynDaemon::onStartTyping()
{
    if ( !mBypassTimer.isActive() && isDaemonActive() && isTouchPadActive() )
        emit startTyping();

    mBypassTimer.start();
}

void SynDaemon::onStopTyping()
{
  if ( !hasKeyboardActivity() && isDaemonActive() && isTouchPadActive())
    emit stopTyping();
  else
    mBypassTimer.start();
}

void SynDaemon::setDelay( unsigned int delay )
{
  unsigned int min = 10;
  unsigned int max = 2000;
  mBypassTimer.setInterval( qBound( min, delay, max ) );
}

unsigned int SynDaemon::delay() const
{
  return mBypassTimer.interval();
}

void SynDaemon::setDaemonActive( bool active )
{
    qDebug() << "set daemon" << active;
    mDaemonActive = active;
}

bool SynDaemon::isDaemonActive() const
{
    return mDaemonActive;
}

void SynDaemon::rollbackSettings()
{
    QSettings settings("TouchFreeze");
    setDelay( settings.value( "syndaemon/delay", 500 ).toUInt() );
    setDaemonActive( settings.value( "syndaemon/daemonactive", true ).toBool() );
    setTouchPadActive( settings.value( "syndaemon/touchpadactive", true ).toBool() );  
}

void SynDaemon::commitSettings()
{
  QSettings settings("TouchFreeze");

  settings.setValue("syndaemon/delay",delay());
  settings.setValue("syndaemon/daemonactive",isDaemonActive());
  settings.setValue("syndaemon/touchpadactive",isTouchPadActive());
  
  settings.sync();
}

SynDaemon::~SynDaemon()
{
//  qDebug() << "Syndaemon::~Syndaemon";
  
  if ( !mDisplay )
    XCloseDisplay( mDisplay );
}

bool SynDaemon::hasKeyboardActivity() const
{
    const unsigned int KEYMAP_SIZE=32;
    static unsigned char oldKeyState[KEYMAP_SIZE];
    unsigned char keyState[KEYMAP_SIZE];

    bool result = false;

    XQueryKeymap( mDisplay, (char*)keyState );

    // find pressed keys
    for ( unsigned int i = 0; i < KEYMAP_SIZE; i++ )
    {
        if ( ( keyState[i] & ~oldKeyState[i] ) )
        {
            result = true;
            break;
        }
    }

    // back up key states...
    for ( unsigned int i = 0; i < KEYMAP_SIZE; i++ )
    {
        oldKeyState[i] = keyState[i];
    }

    return result;
}

void SynDaemon::setTouchPadActive( bool active )
{
  qDebug() << "set pad" << active;
  mTouchPadActive = active;
}

bool SynDaemon::isTouchPadActive() const
{
  return mTouchPadActive;
}

