/*
 This file is part of tdeio_obex.

 Copyright (c) 2003 Mathias Froehlich <Mathias.Froehlich@web.de>

 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 Steet, Fifth Floor,
 Boston, MA 02110-1301, USA.
 */

#include "obex.h"

#include <kdebug.h>
#include <tqapplication.h>
#include <tqeventloop.h>
#include <tqregexp.h>

#include <sys/stat.h>

#include <tqdbusvariant.h>

#define MINIMUM_UID 500

Obex::Obex(TQString &protocol) :
        mProtocol(protocol)
{
    kdDebug() << k_funcinfo << endl;
    KUser user;
    m_effectiveUid = user.uid();
}

Obex::~Obex()
{
    kdDebug() << k_funcinfo << endl;
}

bool Obex::parseURL(const KURL &url, TQString &address, TQString &name, TQString &path) const
{
    kdDebug() << k_funcinfo << endl;
    TQString url_path = url.path(+1);

    if (url_path.find(TQRegExp("/\\[([0-9A-F]{2}:){5}[0-9A-F]{2}\\]"), 0) != -1)
    {
        address = url_path.remove(0, 2);
        address = address.remove(17, url_path.length());
        url_path = url_path.remove(0, 18);
        kdDebug() << "Obex::parseURL address	: " << address << endl;
        kdDebug() << "Obex::parseURL url_path   : " << url_path << endl;
    }
    else
        return false;

    int i = url_path.find('/', 1);
    if (i > 0)
    {
        name = url_path.mid(1, i - 1);
    }
    else
    {
        name = url_path.mid(1);
    }
    path = url_path;
    kdDebug() << "Obex::parseURL path   : " << path << endl;
    kdDebug() << "Obex::parseURL name   : " << name << endl;

    return true;
}

void Obex::addAtom(UDSEntry &entry, UDSAtomTypes type, const TQString &s)
{
    kdDebug() << k_funcinfo << endl;
    UDSAtom atom;
    atom.m_uds = type;
    atom.m_str = s;
    entry.append(atom);
}

void Obex::addAtom(UDSEntry &entry, UDSAtomTypes type, const long l)
{
    kdDebug() << k_funcinfo << endl;
    UDSAtom atom;
    atom.m_uds = type;
    atom.m_long = l;
    entry.append(atom);
}

void Obex::createTopLevelEntry(UDSEntry &entry)
{
    kdDebug() << k_funcinfo << endl;

    entry.clear();
    addAtom(entry, UDS_NAME, ".");
    addAtom(entry, UDS_FILE_TYPE, S_IFDIR);
    addAtom(entry, UDS_ACCESS, 0555);
    addAtom(entry, UDS_MIME_TYPE, "inode/directory");
    addAtom(entry, UDS_ICON_NAME, "pda_blue");
    addAtom(entry, UDS_USER, "root");
    addAtom(entry, UDS_GROUP, "root");
}

void Obex::createDirEntry(UDSEntry &entry, const TQString dir)
{
    kdDebug() << k_funcinfo << endl;
    entry.clear();
    addAtom(entry, UDS_NAME, "/" + dir);
    addAtom(entry, UDS_FILE_TYPE, S_IFDIR);
    addAtom(entry, UDS_ACCESS, 0755);
    addAtom(entry, UDS_MIME_TYPE, "inode/directory");
    addAtom(entry, UDS_ICON_NAME, "pda_blue");
    addAtom(entry, UDS_USER, "root");
    addAtom(entry, UDS_GROUP, "root");
}

void Obex::slotStatResult(Job *job)
{
    kdDebug() << k_funcinfo << endl;
    if (job->error() == 0)
    {
        StatJob *stat_job = static_cast<StatJob *>(job);
        m_entryBuffer = stat_job->statResult();
    }

    tqApp->eventLoop()->exitLoop();
}

UDSEntry Obex::createUDSEntry(const TQMap<TQString, TQT_DBusData> &map)
{
    kdDebug() << k_funcinfo << endl;

    UDSEntry entry;
    long mode;
    uint isFile = 0;

    TQMap<TQString, TQT_DBusData>::const_iterator mit = map.begin();
    for (mit; mit != map.end(); ++mit)
    {

        UDSAtom atom;
        if (mit.key() == "Accessed")
        {
            TQString v = mit.data().toVariant().value.toString();
            atom.m_uds = UDS_ACCESS_TIME;
            atom.m_long = stringToTime_t(v);
            entry.append(atom);
        }
        if (mit.key() == "Created")
        {
            TQString v = mit.data().toVariant().value.toString();
            atom.m_uds = UDS_CREATION_TIME;
            atom.m_long = stringToTime_t(v);
            entry.append(atom);
        }
        if (mit.key() == "Group-perm")
        {
            TQString v = mit.data().toVariant().value.toString();
            if (v.contains('R', false))
                mode |= S_IRGRP;
            if (v.contains('W', false))
                mode |= S_IWGRP;
        }
        if (mit.key() == "Modified")
        {
            TQString v = mit.data().toVariant().value.toString();
            atom.m_uds = UDS_MODIFICATION_TIME;
            atom.m_long = stringToTime_t(v);
            entry.append(atom);
        }
        if (mit.key() == "Size")
        {
            TQ_UINT64 v = mit.data().toVariant().value.toUInt64();
            atom.m_uds = UDS_SIZE;
            atom.m_long = v;
            entry.append(atom);
        }
        if (mit.key() == "Name")
        {
            TQString v = mit.data().toVariant().value.toString();
            atom.m_uds = UDS_NAME;
            atom.m_str = v;
            entry.append(atom);
        }
        if (mit.key() == "Other-perm")
        {
            TQString v = mit.data().toVariant().value.toString();
            if (v.contains('R', false))
                mode |= S_IROTH;
            if (v.contains('W', false))
                mode |= S_IWOTH;
        }
        if (mit.key() == "Type")
        {
            TQString v = mit.data().toVariant().value.toString();
            if (v == "folder")
            {
                isFile = 1;
            }
            if (v == "file")
            {
                TQString v = mit.data().toVariant().value.toString();
                isFile = 2;
            }
        }
        if (mit.key() == "User-perm")
        {
            TQString v = mit.data().toVariant().value.toString();
            if (v.contains('R', false))
                mode |= S_IRUSR;
            if (v.contains('W', false))
                mode |= S_IWUSR;
        }
    }

    if (isFile == 1)
    {
        if (mode & S_IRUSR)
            mode |= S_IXUSR;
        if (mode & S_IRGRP)
            mode |= S_IXGRP;
        if (mode & S_IROTH)
            mode |= S_IXOTH;

        UDSAtom atom;
        atom.m_uds = UDS_ACCESS;
        atom.m_long = mode;
        entry.append(atom);

        // set the file type
        atom.m_uds = UDS_FILE_TYPE;
        atom.m_long = S_IFDIR;
        entry.append(atom);
    }
    else if (isFile == 2)
    {
        UDSAtom atom;
        atom.m_uds = UDS_ACCESS;
        atom.m_long = mode;
        entry.append(atom);

        // set the file type
        atom.m_uds = UDS_FILE_TYPE;
        atom.m_long = S_IFREG;
        entry.append(atom);
    }
    else
    {
        //FIXME fall back
    }
    return entry;
}

time_t Obex::stringToTime_t(TQString str)
{
    kdDebug() << k_funcinfo << endl;

    str.insert(13, ':');
    str.insert(11, ':');
    str.insert(6, '-');
    str.insert(4, '-');
    TQDateTime time = TQDateTime::fromString(str, TQt::ISODate);

    return time.toTime_t();
}

UDSEntry Obex::extractUrlInfos(const KURL &url)
{
    kdDebug() << k_funcinfo << endl;

    m_entryBuffer.clear();

    StatJob *job = stat(url, false);
    connect(job, TQ_SIGNAL(result(Job *)), this, TQ_SLOT(slotStatResult(Job *)));
    tqApp->eventLoop()->enterLoop();

    UDSEntry::iterator it = m_entryBuffer.begin();
    UDSEntry::iterator end = m_entryBuffer.end();

    UDSEntry infos;

    for (; it != end; ++it)
    {
        switch ((*it).m_uds)
        {
        case UDS_ACCESS:
        case UDS_USER:
        case UDS_GROUP:
        case UDS_CREATION_TIME:
        case UDS_MODIFICATION_TIME:
        case UDS_ACCESS_TIME:
            infos.append(*it);
            break;
        default:
            break;
        }
    }

    addAtom(infos, UDS_LOCAL_PATH, url.path());

    return infos;
}

#include "obex.moc"
