#include "halobject.h"

#define HAL_SERVICE "org.freedesktop.Hal"
#define HAL_PATH_MANAGER "/org/freedesktop/Hal/Manager"
#define HAL_PATH_DEVICE "/org/freedesktop/Hal/Device"
#define HAL_OBJECT_MANAGER "org.freedesktop.Hal.Manager"
#define HAL_OBJECT_DEVICE "org.freedesktop.Hal.Device"


halObject::halObject(QObject *parent):QObject(parent),m_bus(QDBusConnection::systemBus()) {
   m_bus.connect( "org.freedesktop.Hal", "/org/freedesktop/Hal/Manager","org.freedesktop.Hal.Manager", "DeviceAdded", this, SLOT( deviceAdded(const QString &) ) );
   m_bus.connect( "org.freedesktop.Hal", "/org/freedesktop/Hal/Manager","org.freedesktop.Hal.Manager", "DeviceRemoved", this, SLOT( deviceRemoved(const QString &) ) );

}

void halObject::deviceAdded(const QString &DiscUdi) {
    if( isDisc( DiscUdi ) ) {
       QString dev,vol;
       devProperties(DiscUdi,dev,vol);
       emit discInserted(dev,vol);

    }
}

void halObject::deviceRemoved(const QString &DiscUdi) {
if( isDisc( DiscUdi ) ) {
       QString dev,vol;
        devProperties(DiscUdi,dev,vol);
        emit discEjected(dev,vol);
    }
}

bool halObject::boolReplyMessageHandler( QDBusMessage replyMsg ) {
    if( replyMsg.type() != QDBusMessage::ReplyMessage )     {
        qDebug() << replyMsg;
        qDebug() << "returning false!";
        return false;
    } else {
        return replyMsg.arguments().first().toBool();
    }
}

bool halObject::isDisc( QString DiscUdi ) {
    QDBusInterface myhalinterface("org.freedesktop.Hal", DiscUdi, "org.freedesktop.Hal.Device",m_bus );
    QDBusMessage replyMsg = myhalinterface.call( "GetPropertyBoolean", "volume.is_disc" );
    return boolReplyMessageHandler( replyMsg );
}

void halObject::devProperties( QString DiscUdi,QString &_dev,QString &_vol ) {
    QDBusInterface myhalinterface("org.freedesktop.Hal", DiscUdi, "org.freedesktop.Hal.Device",m_bus );
    QDBusReply<QString> d = myhalinterface.call( "GetProperty", "block.device" );
    QDBusReply<QString> v = myhalinterface.call( "GetProperty", "volume.label" );
    _vol  = v.value();
    _dev= d.value();
}



QMap <QString,QString> halObject::getVolumeList()
{
     QMap <QString,QString> devices;
    devices.clear();
    if( !QDBusConnection::systemBus().isConnected() ) {
        qDebug("Cannot connect to D-BUS session bus.");
        return devices;
    }

    QDBusInterface hal( HAL_SERVICE, HAL_PATH_MANAGER , HAL_OBJECT_MANAGER, QDBusConnection::systemBus() );
    if (!hal.isValid() ) {
        qDebug( "Couldn't find HAL. Is HAL running?" );
        return devices;
    }

    QDBusReply<QStringList> reply = hal.call( "FindDeviceStringMatch", "volume.disc.type", "dvd_rom" );
    if( !reply.isValid() ) {
        qDebug( "Couldn't call FindDeviceStringMatch." );
        return devices;
    }

    if( reply.value().count() > 0 ) {
        foreach ( QString udi, reply.value() ) {
            QDBusInterface halDev( HAL_SERVICE, udi, HAL_OBJECT_DEVICE, QDBusConnection::systemBus() );
            QDBusReply<bool> isVideo = halDev.call( "GetProperty", "volume.disc.is_videodvd" );
            if( !isVideo.value() ) {
                continue;
            }
            QDBusReply<QString> d = halDev.call( "GetProperty", "block.device" );
            QDBusReply<QString> v = halDev.call( "GetProperty", "volume.label" );

            QString label = v.value();

            devices.insert( d.value(), label );
            emit discInserted(d.value(),label);
        }
    }
   /* else
    {
        devices.insert( tr("none detected"), tr("Insert a DVD...") );
    }
*/
    return devices;
}

QMap <QString,QString> halObject::getDriveList(bool burner)
{
    QMap <QString,QString> devices;
    devices.clear();
    if( !QDBusConnection::systemBus().isConnected() ) {
        qDebug("Cannot connect to D-BUS session bus.");
        return devices;
    }

    QDBusInterface hal( HAL_SERVICE, HAL_PATH_MANAGER , HAL_OBJECT_MANAGER, QDBusConnection::systemBus() );
    if (!hal.isValid() ) {
        qDebug( "Couldn't find HAL. Is HAL running?" );
        return devices;
    }

    QDBusReply<QStringList> reply = hal.call( "FindDeviceStringMatch", "storage.drive_type", "cdrom" );
    if( !reply.isValid() ) {
        qDebug( "Couldn't call FindDeviceStringMatch." );
        return devices;
    }

    if( reply.value().count() > 0 ) {
        foreach ( QString udi, reply.value() ) {
            QDBusInterface halDev( HAL_SERVICE, udi, HAL_OBJECT_DEVICE, QDBusConnection::systemBus() );
            QDBusReply<bool> isVideo = halDev.call( "GetProperty","storage.cdrom.dvd" );
            if( !isVideo.value() ) {
                continue;
            }
            QDBusReply<bool> dvdr = halDev.call( "GetProperty","storage.cdrom.dvdr" );
            QDBusReply<bool> dvdplusr = halDev.call( "GetProperty","storage.cdrom.dvdplusr" );
            if (!dvdr.value() && !dvdplusr.value() && burner) {
                continue;
            }
            QDBusReply<QString> d = halDev.call( "GetProperty", "block.device" );
            QDBusReply<QString> model = halDev.call( "GetProperty", "storage.model");
            QDBusReply<QString> vendor = halDev.call( "GetProperty", "storage.vendor");
            QDBusReply<QStringList> speeds=halDev.call("GetProperty","storage.cdrom.write_speeds");

            devices.insert( d.value(), vendor.value() +" " +model.value() );
            emit deviceAdded(d.value(),vendor.value() +" "+model.value(),dvdr.value() ||dvdplusr.value(),speeds);
        }
    }


    return devices;
}
