#include "mythinputlirc.h"
#include <QtPlugin>
#include <QKeyEvent>
#include <QFile>
#include <QtGlobal>
#include <QStringList>
#include <QDir>


MythInputLirc::MythInputLirc()
    :m_lircSocket(0),
    m_inputManager(0)
{
    connect(&m_lircSocket, SIGNAL(readyRead()), 
            this, SLOT(slotRead()));
    connect(&m_lircSocket, SIGNAL(error(QLocalSocket::LocalSocketError)), 
            this,SLOT(socketError(QLocalSocket::LocalSocketError)));
    connect(&m_lircSocket, SIGNAL(connected()), 
            this, SLOT(socketConnected()));
};

MythInputLirc::~MythInputLirc()
{
    m_mapping.clear();
}

void MythInputLirc::setInputManager(MythInputManagerInterface * inputManager)
{
    if (inputManager==NULL)
        stop();
    m_inputManager=inputManager;
}

void MythInputLirc::start()
{
    if (loadConfig())
    {
        QString device=m_inputManager->getSetting(this,"device","/var/run/lirc/lircd");
        m_lircSocket.connectToServer(device , QIODevice::ReadWrite);
    }

}

bool MythInputLirc::loadConfig()
{
    if (m_inputManager == NULL)
    {
        qWarning() << QString("MythInputLirc can not start without an input manager");
        return false;
    }
    m_mapping.clear();
    bool begin=false;

    m_configFile=m_inputManager->getSetting(this, "configfile",QString("%1/.lircrc2").arg(QDir::homePath()));
    QFile file(m_configFile);
    if(!file.open(QIODevice::ReadOnly))
    {
        m_inputManager->logError(QString("MythInputLirc: Cannot open config file \"%1\"").arg(file.fileName()));
        return false;
    }

    QTextStream in(&file);
    QString program;
    QString remote;
    QString button;
    QString config;

    int lineNumber=0;
    int beginNumber=0;


    while(!in.atEnd()) {
        QString line = in.readLine().trimmed();    

        if (line.isEmpty() || line.startsWith("#")) continue;

        if (begin)
        {
            if (line.trimmed().toLower().compare("end")==0)
            {
                begin=false;
                if (program.isEmpty())
                {
                    m_inputManager->logError(QString("MythInputLirc: prog is empty between line %1 and %2")
                                .arg(beginNumber)
                                .arg(lineNumber));
                }
                else if (program.compare("mythtv")==0)
                {
                    if (!remote.isEmpty()
                        && !button.isEmpty()
                        && !config.isEmpty())
                    {

                        QKeySequence keyseq(config);

                        if (keyseq.count()>0)
                        {
                            m_inputManager->logDebug(QString("MythInputLirc: Valid entry: remote=%1 button=%2 config=%3")
                                .arg(remote)
                                .arg(button)
                                .arg(config));
                            QMap<QString,QString> remoteMapping = m_mapping[remote];
                            remoteMapping[button]=config;
                            m_mapping[remote]=remoteMapping;
                        }
                        else
                            m_inputManager->logWarning(QString("MythInputLirc: Invalid entry: remote=%1 button=%2 config=%3 between line %4 and %5")
                                .arg(remote)
                                .arg(button)
                                .arg(config)
                                .arg(beginNumber)
                                .arg(lineNumber));
                    }
                    else
                        m_inputManager->logWarning(QString("MythInputLirc: Invalid entry: remote=%1 button=%2 config=%3 between line %4 and %5")
                            .arg(remote)
                            .arg(button)
                            .arg(config)
                            .arg(beginNumber)
                            .arg(lineNumber));
                }
            }
            else
            {
                QStringList couple = line.split("=");
                if (couple.size()==2)
                {
                    QString name=couple[0].trimmed();
                    if (name.compare("prog")==0)
                    {
                        program=couple[1].trimmed();
                    }
                    else if (name.compare("remote")==0)
                    {
                        remote=couple[1].trimmed();
                    }
                    else if (name.compare("button")==0)
                    {
                        button=couple[1].trimmed();
                    }
                    else if (name.compare("config")==0)
                    {
                        config=couple[1].trimmed();
                    }
                }
                else
                    m_inputManager->logWarning(QString("MythInputLirc: unknown key word line %1")
                        .arg(lineNumber));
            }
        }
        else if (line.trimmed().toLower().compare("begin")==0)
        {
            begin=true;
            program = QString("");
            remote  = QString("");
            button  = QString("");
            config  = QString("");
            beginNumber=lineNumber;
        }
        else
        {
            m_inputManager->logWarning(QString("MythInputLirc: unknown key word line %1")
                        .arg(lineNumber));
        }
        lineNumber++;
    }

    file.close();
    return true;
}


void MythInputLirc::slotRead()
{
    while (m_lircSocket.bytesAvailable()) {
    {
        QByteArray 	line = m_lircSocket.readLine ( 255 );
        QStringList codes=QString(line).trimmed().split(" ");
        if (codes.size()==4)
        {
            QString remote = codes[3];
            QString button = codes[2];
            QString repeat = codes[1];
            m_inputManager->logDebug(QString("MythInputLirc button: remote=%1 button=%2 repeat=%3")
                .arg(remote)
                .arg(button)
                .arg(repeat));
            if (m_mapping.contains(remote))
            {
                if (m_mapping[remote].contains(button))
                {
                    QKeySequence keyseq(m_mapping[remote][button]);
                    if (keyseq.count()>0)
                        m_inputManager->onKeyPressed(
                            QKeyEvent(QEvent::KeyPress, keyseq[0],Qt::NoModifier));
                    else
                        m_inputManager->logWarning(QString("MythInputLirc: cannot convert %1 to QKeyEvent")
                            .arg(m_mapping[remote][button]));
                }
                else
                    m_inputManager->logWarning(QString("MythInputLirc: button not found: remote=%1 button=%2 repeat=%3")
                        .arg(remote)
                        .arg(button)
                        .arg(repeat));
            }
            else
                m_inputManager->logWarning(QString("MythInputLirc: remote does not exist: remote=%1 button=%2 repeat=%3")
                    .arg(remote)
                    .arg(button)
                    .arg(repeat));
             
        }
        else
            m_inputManager->logWarning(QString("MythInputLirc read: %1").arg(QString(line)));
    }


    }
}

void MythInputLirc::socketError(QLocalSocket::LocalSocketError socketError)
{
    m_inputManager->logError(QString("MythInputLirc Error: %1 code(%2)")
        .arg( m_lircSocket.errorString()).arg(socketError)) ;
}
void MythInputLirc::socketConnected()
{
    m_inputManager->logInfo(QString("MythInputLirc: Connected to %1 using %2 config file")
        .arg(m_lircSocket.fullServerName())
        .arg(m_configFile));
}

void MythInputLirc::stop()
{
    m_lircSocket.disconnectFromServer();
}

const QString MythInputLirc::name() const
{
    return "lirc";
}

const QString MythInputLirc::description() const
{
    return "Linux Infrared Remote Control example i.e not full featured";
}


Q_EXPORT_PLUGIN2(mythinputlirc, MythInputLirc);
