/* This file is part of the KDE libraries
    Copyright (C) 2009 Norbert Frese <nf2.email@gmail.com>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library 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
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.
 */

#include "gionetworkstorage.h"
#include <kdebug.h>
#include <QtCore/QPointer>
#include <kurl.h>

static void _mount_unmounted (
        GVolume         *gVolume,
        gpointer        user_data)
{

    QPointer<GioNetworkStorage> * p = (QPointer<GioNetworkStorage> *)user_data;
    if (!p->isNull())
    {
        (*p)->_slotRemoved();
    }
}

static void _mount_changed (
        GVolume         *gVolume,
        gpointer        user_data)
{
    QPointer<GioNetworkStorage> * p = (QPointer<GioNetworkStorage> *)user_data;
    if (!p->isNull())
    {
        (*p)->_slotChanged();
    }
}

static void myGClosureNotify(gpointer data, GClosure *closure)
{
    QPointer<GioNetworkStorage> * p = (QPointer<GioNetworkStorage> *)data;
    delete p;
}

GioNetworkStorage::GioNetworkStorage(GMount * gMount)
{
    m_isValid = true;
    m_gMount = gMount;
    g_object_ref(m_gMount);

    {
        QPointer<GioNetworkStorage> * p = new QPointer<GioNetworkStorage>(this);

        GClosure* closure = g_cclosure_new(G_CALLBACK(_mount_unmounted),
                p,
                myGClosureNotify);

        g_signal_connect_closure(m_gMount,
                "unmounted",
                closure,
                TRUE);
    }

    {
        QPointer<GioNetworkStorage> * p = new QPointer<GioNetworkStorage>(this);

        GClosure* closure = g_cclosure_new(G_CALLBACK(_mount_changed),
                p,
                myGClosureNotify);

        g_signal_connect_closure(m_gMount,
                "changed",
                closure,
                TRUE);
    }

}


GioNetworkStorage::~GioNetworkStorage()
{
    g_object_unref(m_gMount);
}

bool GioNetworkStorage::isValid() const
{
    return m_isValid;
}

QString GioNetworkStorage::id() const
{
    char * uuid = g_mount_get_name(m_gMount);

    QString uuidStr = QString(uuid);
    g_free(uuid);

    return uuidStr;
}

QString GioNetworkStorage::displayName() const
{
    char * name = g_mount_get_name(m_gMount);

    QString nameStr = QString(name);
    g_free(name);

    return nameStr;
}

QString GioNetworkStorage::icon() const
{
    GIcon * gIcon;

    gIcon = g_mount_get_icon(m_gMount);

    if (gIcon != NULL && G_IS_THEMED_ICON(gIcon))
    {
        GThemedIcon * gThemedIcon = G_THEMED_ICON(gIcon);
        const gchar* const * iconNames = g_themed_icon_get_names (gThemedIcon);
        guint numIconNames = g_strv_length((gchar**)iconNames);

        if (numIconNames>0)
        {
            return QString(iconNames[0]);
        }
        g_object_unref(gIcon);
    }
    return "network-server";
}

QStringList GioNetworkStorage::emblems() const
{
    QStringList res;
    res << "emblem-mounted";
    return res;
}


QUrl GioNetworkStorage::url() const
{
    GFile * root = g_mount_get_root(m_gMount);
    char * uri = g_file_get_uri(root);
    QString uriStr = QString(uri);
    g_free(uri);
    g_object_unref(root);
    return QUrl(KUrl(uriStr));
}

QString GioNetworkStorage::mountPointPath() const
{
    return QString();
}

bool GioNetworkStorage::isRemovable() const
{
    return false;
}

bool GioNetworkStorage::isReleasable() const
{
    return false;
}

bool GioNetworkStorage::isHotpluggable() const
{
    return false;
}

bool GioNetworkStorage::isAccessible() const
{
    return true;
}

KDiskFreeSpaceInfo GioNetworkStorage::freeSpace() const
{
    return KDiskFreeSpaceInfo::freeSpaceInfo(QString());
}


///// disconnect /////

static void _unmountReadyCallback(GObject *source_object,
        GAsyncResult *res,
        gpointer user_data)
{
    QPointer<GioNetworkStorage> * p = (QPointer<GioNetworkStorage> *)user_data;
    if (!p->isNull())
    {
        GError * gError = NULL;
        QString errorMsg;

        KStorage::ErrorType error = KStorage::NoError;

        if (!g_mount_unmount_finish(G_MOUNT(source_object),
                res,
                &gError))
        {
            error = KStorage::UnauthorizedOperation;
            errorMsg = gError->message;
            g_error_free(gError);
        }

        (*p)->_slotEjectDone(KStorage(new GioNetworkStorage(G_MOUNT(source_object))), error, errorMsg);
        delete p;
    }
}

void GioNetworkStorage::tearDown(QObject *doneSignalTarget, const char *doneSlot)
{


    QPointer<GioNetworkStorage> * p = new QPointer<GioNetworkStorage>(this);

    g_mount_unmount(m_gMount,
            G_MOUNT_UNMOUNT_NONE,
            NULL,
            _unmountReadyCallback,
            p);

    connect(this, SIGNAL(teardownDone(const KStorage &, const KStorage::ErrorType, const QString &)),
            doneSignalTarget, doneSlot);

}


