/*
 * tasks.h - basic tasks
 * Copyright (C) 2001, 2002  Justin Karneges
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 *
 */

#ifndef JABBER_TASKS_H
#define JABBER_TASKS_H

#include <QString>
#include <QtXml>
#include <QList>

#include "im.h"
#include "xmpp_vcard.h"
#include "xmpp_discoinfotask.h"
#include "xmpp_subsets.h"
#include "xmpp_encryptionhandler.h"

namespace XMPP
{
    class Roster;
    class Status;
    class BoBData;
    class CaptchaChallenge;

    class JT_Register : public Task
    {
        Q_OBJECT
    public:
        JT_Register(Task *parent);
        ~JT_Register();

        // OLd style registration
        void reg(const QString &user, const QString &pass);

        void changepw(const QString &pass);
        void unreg(const Jid &j="");

        const Form & form() const;
        bool hasXData() const;
        const XData& xdata() const;
        bool isRegistered() const;
        void getForm(const Jid &);
        void setForm(const Form &);
        void setForm(const Jid&, const XData &);

        void onGo();
        bool take(const QDomElement &);

    private:
        QDomElement iq;
        Jid to;

        class Private;
        Private *d = nullptr;
    };

    class JT_UnRegister : public Task
    {
        Q_OBJECT
    public:
        JT_UnRegister(Task *parent);
        ~JT_UnRegister();

        void unreg(const Jid &);

        void onGo();

    private slots:
        void getFormFinished();
        void unregFinished();

    private:
        class Private;
        Private *d = nullptr;
    };

    class JT_Roster : public Task
    {
        Q_OBJECT
    public:
        JT_Roster(Task *parent);
        ~JT_Roster();

        void get();
        void set(const Jid &, const QString &name, const QStringList &groups);
        void remove(const Jid &);

        // XEP-0083
        void getGroupsDelimiter();
        void setGroupsDelimiter(const QString &groupsDelimiter);

        const Roster & roster() const;
        QString groupsDelimiter() const;

        QString toString() const;
        bool fromString(const QString &);

        void onGo();
        bool take(const QDomElement &x);

    private:
        int type;
        QDomElement iq;
        Jid to;

        class Private;
        Private *d = nullptr;
    };

    class JT_PushRoster : public Task
    {
        Q_OBJECT
    public:
        JT_PushRoster(Task *parent);
        ~JT_PushRoster();

        bool take(const QDomElement &);

    signals:
        void roster(const Roster &);

    private:
        class Private;
        Private *d = nullptr;
    };

    class JT_Presence : public Task
    {
        Q_OBJECT
    public:
        JT_Presence(Task *parent);
        ~JT_Presence();

        void pres(const Status &);
        void pres(const Jid &, const Status &);
        void sub(const Jid &, const QString &subType, const QString& nick = QString());
        void probe(const Jid &to);

        void onGo();

    private:
        QDomElement tag;
        int type = -1;

        class Private;
        Private *d = nullptr;
    };

    class JT_PushPresence : public Task
    {
        Q_OBJECT
    public:
        JT_PushPresence(Task *parent);
        ~JT_PushPresence();

        bool take(const QDomElement &);

    signals:
        void presence(const Jid &, const Status &);
        void subscription(const Jid &, const QString &, const QString&);

    private:
        class Private;
        Private *d = nullptr;
    };

    class JT_Session : public Task
    {
    public:
        JT_Session(Task *parent);
        void onGo();
        bool take(const QDomElement&);
    };

    class JT_Message : public Task
    {
        Q_OBJECT
    public:
        JT_Message(Task *parent, Message &);
        ~JT_Message();

        void onGo();

    private:
        Message m;

        class Private;
        Private *d = nullptr;
    };

    class JT_PushMessage : public Task
    {
        Q_OBJECT
    public:
        JT_PushMessage(Task *parent, EncryptionHandler *encryptionHandler = nullptr);
        ~JT_PushMessage();

        bool take(const QDomElement &);

    signals:
        void message(const Message &);

    private:
        class Private;
        Private *d = nullptr;
    };

    class JT_VCard : public Task
    {
        Q_OBJECT
    public:
        JT_VCard(Task *parent);
        ~JT_VCard();

        void get(const Jid &);
        void set(const VCard &);
        void set(const Jid &, const VCard &, bool isTarget = false);

        const Jid & jid() const;
        const VCard  & vcard() const;

        void onGo();
        bool take(const QDomElement &x);

    private:
        int type;

        class Private;
        Private *d = nullptr;
    };

    class JT_Search : public Task
    {
        Q_OBJECT
    public:
        JT_Search(Task *parent);
        ~JT_Search();

        const Form & form() const;
        const QList<SearchResult> & results() const;

        bool hasXData() const;
        const XData & xdata() const;

        void get(const Jid &);
        void set(const Form &);
        void set(const Jid &, const XData &);

        void onGo();
        bool take(const QDomElement &x);

    private:
        QDomElement iq;
        int type;

        class Private;
        Private *d = nullptr;
    };

    class JT_ClientVersion : public Task
    {
        Q_OBJECT
    public:
        JT_ClientVersion(Task *);

        void get(const Jid &);
        void onGo();
        bool take(const QDomElement &);

        const Jid & jid() const;
        const QString & name() const;
        const QString & version() const;
        const QString & os() const;

    private:
        QDomElement iq;

        Jid j;
        QString v_name, v_ver, v_os;
    };

    class JT_EntityTime : public Task
    {
    public:
        JT_EntityTime(Task*);

        void onGo();
        bool take(const QDomElement &);
        void get(const XMPP::Jid &j);
        const XMPP::Jid & jid() const;

        const QDateTime & dateTime() const;
        int timezoneOffset() const;

    private:
        QDomElement iq;
        XMPP::Jid j;
        QDateTime utc;
        int tzo = 0;
    };

    class JT_ServInfo : public Task
    {
        Q_OBJECT
    public:
        JT_ServInfo(Task *);
        ~JT_ServInfo();

        bool take(const QDomElement &);
    };

    class JT_Gateway : public Task
    {
        Q_OBJECT
    public:
        JT_Gateway(Task *);

        void get(const Jid &);
        void set(const Jid &, const QString &prompt);
        void onGo();
        bool take(const QDomElement &);

        Jid jid() const;

        QString desc() const;
        QString prompt() const;
        Jid translatedJid() const;

    private:
        QDomElement iq;

        int type;
        Jid v_jid;
        Jid v_translatedJid;
        QString v_prompt, v_desc;
    };

    class JT_DiscoItems : public Task
    {
        Q_OBJECT
    public:
        JT_DiscoItems(Task *);
        ~JT_DiscoItems();

        void get(const Jid &, const QString &node = QString::null);
        void get(const DiscoItem &);

        const DiscoList &items() const;

        void includeSubsetQuery(const SubsetsClientManager &);
        bool extractSubsetInfo(SubsetsClientManager &);

        void onGo();
        bool take(const QDomElement &);

    private:
        class Private;
        Private *d = nullptr;
    };

    class JT_DiscoPublish : public Task
    {
        Q_OBJECT
    public:
        JT_DiscoPublish(Task *);
        ~JT_DiscoPublish();

        void set(const Jid &, const DiscoList &);

        void onGo();
        bool take(const QDomElement &);

    private:
        class Private;
        Private *d = nullptr;
    };

    class JT_BoBServer : public Task
    {
        Q_OBJECT

    public:
        JT_BoBServer(Task *parent);
        bool take(const QDomElement &);
    };

    class JT_BitsOfBinary : public Task
    {
        Q_OBJECT
    public:
        JT_BitsOfBinary(Task *);
        ~JT_BitsOfBinary();

        void get(const Jid &, const QString &);

        void onGo();
        bool take(const QDomElement &);
        BoBData &data();

    private:
        class Private;
        Private *d = nullptr;
    };

    class JT_PongServer : public Task
    {
        Q_OBJECT
    public:
        JT_PongServer(Task *);
        bool take(const QDomElement &);
    };

    class JT_MessageCarbons : public Task
    {
        Q_OBJECT

    public:
        JT_MessageCarbons(Task *parent);
        void enable();
        void disable();

        void onGo();
        bool take(const QDomElement &e);

    private:
        QDomElement _iq;
    };

    class JT_CaptchaChallenger : public Task
    {
        Q_OBJECT
    public:
        const static int CaptchaValidTimeout = 120;

        JT_CaptchaChallenger(Task *);
        ~JT_CaptchaChallenger();

        void set(const Jid &, const CaptchaChallenge &);

        void onGo();
        bool take(const QDomElement &);

    private:
        class Private;
        Private *d = nullptr;
    };

    class JT_CaptchaSender : public Task
    {
        Q_OBJECT
    public:
        JT_CaptchaSender(Task *);

        void set(const Jid &, const XData &);

        void onGo();
        bool take(const QDomElement &);

    private:
        Jid to;
        QDomElement iq;
    };
}

#endif
