/*
    Implementation of the main dialog.
    Copyright (C) 2007 Tim Beaulen <tbscope@gmail.com>

    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 "backenddebuggerform.h"

#include <QGraphicsScene>
#include <QPalette>
#include <QBrush>
#include <QTreeWidgetItem>
#include <QTreeWidgetItemIterator>
#include <QPixmap>
#include <QDomDocument>
#include <QDomElement>
#include <QDomNode>
#include <QDomNodeList>

#include "../backend.h"

#include <kdebug.h>

BackendDebuggerForm::BackendDebuggerForm(QWidget *parent)
    : QDialog(parent)
{
    ui.setupUi(this);
        
    setupMessageList();
    setupPipelineView();
    setupLevelCombo();
    setupObjectCombo();

    ui.changeList->hide();

    pulseTimer = new QTimer(this);
    connect(pulseTimer, SIGNAL(timeout()), this, SLOT(updateDBusStatus()));
    pulseTimer->start(1000);

    m_pulseIcon = QIcon(":/icons/network.png");
    ui.labelPulse->setPixmap(m_pulseIcon.pixmap(16,16,QIcon::Disabled,QIcon::Off));

    connect(ui.comboObject, SIGNAL(currentIndexChanged(int)), this, SLOT(updateMessageList()));
    connect(ui.comboLevel, SIGNAL(currentIndexChanged(int)), this, SLOT(updateMessageList()));

    m_interface = new PhononGStreamerBackendDebuggerInterface(QString(), QString(), QDBusConnection::sessionBus(), this);
    connect(m_interface, SIGNAL(message(int, int, QString, QString)), this, SLOT(newMessage(int, int, QString, QString)));
    connect(m_interface, SIGNAL(backendCreated(QString)), this, SLOT(newBackend(QString)));
    connect(m_interface, SIGNAL(backendUpdated(QString)), this, SLOT(updateBackend(QString)));
    connect(m_interface, SIGNAL(backendDestroyed(QString)), this, SLOT(removeBackend(QString)));
}

void BackendDebuggerForm::setupPipelineView()
{
    QGraphicsScene *scene = new QGraphicsScene(ui.pipelineView);
    scene->setItemIndexMethod(QGraphicsScene::NoIndex);
    scene->setSceneRect(-10,-10,400,400);
    scene->setBackgroundBrush(QBrush(qRgb(100,100,100)));
    ui.pipelineView->setAlignment(Qt::AlignLeft | Qt::AlignTop);
   // scene->addRect(scene->sceneRect());
    ui.pipelineView->setScene(scene);
    QBrush bg;
    bg.setTexture(QPixmap(":/icons/background.png"));
    scene->setBackgroundBrush(bg);
    ui.pipelineView->setCacheMode(QGraphicsView::CacheBackground);
    ui.pipelineView->setRenderHint(QPainter::Antialiasing);
}

void BackendDebuggerForm::setupLevelCombo()
{
    ui.comboLevel->addItem("Level 0   = Creation, destruction, warnings and errors");
    ui.comboLevel->addItem("Level 1   = Level 0 + very important information");
    ui.comboLevel->addItem("Level 2   = Level 1 + important information");
    ui.comboLevel->addItem("Level 3   = Level 2 + a lot of information");
    ui.comboLevel->addItem("Level 4 + = Full debug");

    ui.comboLevel->setCurrentIndex(4);
}

void BackendDebuggerForm::setupMessageList()
{
    ui.messageList->setRootIsDecorated(false);
    ui.messageList->setColumnWidth(0, 20);
    ui.messageList->setColumnHidden(1, true);
}

void BackendDebuggerForm::setupObjectCombo()
{
    ui.comboObject->addItem("All objects");
    ui.comboObject->setCurrentIndex(0);
    ui.comboObject->setSizeAdjustPolicy(QComboBox::AdjustToContents);
}

void BackendDebuggerForm::newMessage(int type, int level, const QString &objname, const QString &message)
{
    QTreeWidgetItem *item = new QTreeWidgetItem(ui.messageList);

    switch(type) {
    case 0:
        item->setIcon(0, QIcon(":/icons/information.png"));
        break;
    case 1:
        item->setIcon(0, QIcon(":/icons/warning.png"));
        break;
    case 2:
        item->setIcon(0, QIcon(":/icons/error.png"));
        break;
    }

    item->setText(1, QString::number(level));

    // Update object combo box
    if(ui.comboObject->findText(objname) < 0)
        ui.comboObject->addItem(objname);

    item->setText(2, objname);
    item->setText(3, message);

    updateMessageList();
};

void BackendDebuggerForm::updateMessageList()
{
     QTreeWidgetItemIterator it(ui.messageList);
     while (*it) {
         if(ui.comboLevel->currentIndex() == 0) {
             if ((*it)->text(1) == "0")
                 (*it)->setHidden(false);
             else
                 (*it)->setHidden(true);
         }
         else if(ui.comboLevel->currentIndex() == 1) {
             if ((*it)->text(1) == "0" || (*it)->text(1) == "1")
                 (*it)->setHidden(false);
             else
                 (*it)->setHidden(true);
         }
         else if(ui.comboLevel->currentIndex() == 2) {
             if ((*it)->text(1) == "0" || (*it)->text(1) == "1" || (*it)->text(1) == "2")
                 (*it)->setHidden(false);
             else
                 (*it)->setHidden(true);
         }
         else if(ui.comboLevel->currentIndex() == 3) {
             if ((*it)->text(1) == "0" || (*it)->text(1) == "1" || (*it)->text(1) == "2" || (*it)->text(1) == "3")
                 (*it)->setHidden(false);
             else
                 (*it)->setHidden(true);
         }
         else if(ui.comboLevel->currentIndex() == 4) {
             (*it)->setHidden(false);
         }

         if(ui.comboObject->currentIndex() > 0) {
             if ((*it)->text(2) != ui.comboObject->currentText() && !(*it)->isHidden())
                 (*it)->setHidden(true);
         }

         ++it;
    }
}

void BackendDebuggerForm::updateDBusStatus()
{
    QTimer::singleShot(200, this, SLOT(turnOffLed()));
    ui.labelPulse->setPixmap(m_pulseIcon.pixmap(16,16,QIcon::Normal,QIcon::On));

    if(m_interface)
        ui.statusLabel->setText("Connected to org.kde.phonongstreamerbackenddebugger");
    else
        ui.statusLabel->setText("Not connected to org.kde.phonongstreamerbackenddebugger");
}

void BackendDebuggerForm::turnOffLed()
{
    ui.labelPulse->setPixmap(m_pulseIcon.pixmap(16,16,QIcon::Disabled,QIcon::Off));
}

void BackendDebuggerForm::updateSceneBoundingRect()
{
    QRectF r = ui.pipelineView->scene()->itemsBoundingRect();
    r.setLeft(r.left() - 10);
    r.setTop(r.top() - 10);
    r.setRight(r.right() + 10);
    r.setBottom(r.bottom() + 10);

    ui.pipelineView->scene()->setSceneRect(r);

    QRectF updateRect = contentsRect();
    ui.pipelineView->scene()->update(updateRect);
}

void BackendDebuggerForm::newBackend(const QString &xmlStructure)
{
    kDebug() << xmlStructure << endl;

    int top = 0;

    foreach(BackendItem *b, m_backendItems) {
        top += (int)b->boundingRect().height() + 10;
    }

    BackendItem *i = new BackendItem(xmlStructure);
    i->setPos(0,top);
    ui.pipelineView->scene()->addItem(i);

    m_backendItems << i;

    updateSceneBoundingRect();
}

void BackendDebuggerForm::updateBackend(const QString &xmlStructure)
{
    kDebug() << xmlStructure << endl;

    QDomDocument doc;
    doc.setContent(xmlStructure);
    QDomElement backendElement = doc.documentElement();
    QDomNodeList nodelist = backendElement.elementsByTagName("Backend");
    QDomElement e = nodelist.at(0).toElement();

    QString name = e.attribute("Name");

    foreach(BackendItem *b, m_backendItems) {
        if(b->name() == name)
            b->updateStructure(xmlStructure);
    }

    updateSceneBoundingRect();
}

void BackendDebuggerForm::removeBackend(const QString &xmlStructure)
{
    kDebug() << xmlStructure << endl;

    QDomDocument doc;
    doc.setContent(xmlStructure);
    QDomElement backendElement = doc.documentElement();
    QDomNodeList nodelist = backendElement.elementsByTagName("Backend");
    QDomElement e = nodelist.at(0).toElement();

    QString name = e.attribute("Name");

    foreach(BackendItem *b, m_backendItems) {
        if(b->name() == name) {
            m_backendItems.removeAll(b);
            delete b;
            break;
        }
    }

    int top = 0;

    foreach(BackendItem *b, m_backendItems) {
        b->setPos(0, top);
        top += (int)b->boundingRect().height() + 10;
    }

    updateSceneBoundingRect();
}

#include "backenddebuggerform.moc"
