/*
    SPDX-FileCopyrightText: 2005 Joris Guisson <joris.guisson@gmail.com>
    SPDX-License-Identifier: GPL-2.0-or-later
*/

#ifndef KTCOREINTERFACE_H
#define KTCOREINTERFACE_H

#include <QObject>
#include <QUrl>

#include <ktcore_export.h>
#include <util/constants.h>

namespace bt
{
class TorrentInterface;
class MagnetLink;
class TorrentCreator;
}

namespace kt
{
/// Stats struct
struct CurrentStats {
    bt::Uint32 download_speed;
    bt::Uint32 upload_speed;
    bt::Uint64 bytes_downloaded;
    bt::Uint64 bytes_uploaded;
};

struct MagnetLinkLoadOptions {
    bool silently;
    QString group;
    QString location;
    QString move_on_completion;
};

class MagnetManager;
class QueueManager;
class GroupManager;
class DBus;

/**
 * @author Joris Guisson
 * @brief Interface for plugins to communicate with the application's core
 *
 * This interface provides the plugin with the functionality to modify
 * the applications core, the core is responsible for managing all
 * TorrentControl objects.
 */
class KTCORE_EXPORT CoreInterface : public QObject
{
    Q_OBJECT
public:
    CoreInterface();
    ~CoreInterface() override;

    /**
     * Set whether or not we should keep seeding after
     * a download has finished.
     * @param ks Keep seeding yes or no
     */
    virtual void setKeepSeeding(bool ks) = 0;

    /**
     * Change the data dir. This involves copying
     * all data from the old dir to the new.
     * This can offcourse go horribly wrong, therefore
     * if it doesn't succeed it returns false
     * and leaves everything where it supposed to be.
     * @param new_dir The new directory
     */
    virtual bool changeDataDir(const QString &new_dir) = 0;

    /**
     * Start all, takes into account the maximum number of downloads.
     */
    virtual void startAll() = 0;

    /**
     * Stop all torrents.
     */
    virtual void stopAll() = 0;

    /**
     * Start a torrent, takes into account the maximum number of downloads.
     * @param tc The TorrentControl
     */
    virtual void start(bt::TorrentInterface *tc) = 0;

    /**
     * Start a list of torrents.
     * @param todo The list of torrents
     */
    virtual void start(QList<bt::TorrentInterface *> &todo) = 0;

    /**
     * Stop a torrent, may start another download if it hasn't been started.
     * @param tc The TorrentControl
     * @param user true if user stopped the torrent, false otherwise
     */
    virtual void stop(bt::TorrentInterface *tc) = 0;

    /**
     * Stop a list of torrents.
     * @param todo The list of torrents
     */
    virtual void stop(QList<bt::TorrentInterface *> &todo) = 0;

    /**
     * Pause a torrent
     * @param tc The torrent
     */
    virtual void pause(bt::TorrentInterface *tc) = 0;

    /**
     * Pause a list of torrents.
     * @param todo The list of torrents
     */
    virtual void pause(QList<bt::TorrentInterface *> &todo) = 0;

    /// Get CurrentStats structure
    virtual CurrentStats getStats() = 0;

    /**
     * Switch the port
     * @param port The new port
     * @return true if we can, false otherwise
     */
    virtual bool changePort(bt::Uint16 port) = 0;

    ///  Get the number of torrents running (including seeding torrents).
    virtual bt::Uint32 getNumTorrentsRunning() const = 0;

    ///  Get the number of torrents not running.
    virtual bt::Uint32 getNumTorrentsNotRunning() const = 0;

    /**
     * Load a torrent file. Pops up an error dialog
     * if something goes wrong. Will ask the user for a save location, or use
     * the default.
     * @param url The torrent file
     * @param group Group to add torrent to
     */
    virtual void load(const QUrl &url, const QString &group) = 0;

    /**
     * Load a torrent file. Pops up an error dialog
     * if something goes wrong. Will ask the user for a save location, or use
     * the default. This will not popup a file selection dialog for multi file torrents.
     * @param url The torrent file
     * @param group Group to add torrent to
     */
    virtual void loadSilently(const QUrl &url, const QString &group) = 0;

    /**
     * Load a torrent using a byte array
     * @param data Data of the torrent
     * @param url URL of the torrent
     * @param group Group to use
     * @param savedir Directory to save to
     * @return The loaded TorrentInterface or 0 on failure
     */
    virtual bt::TorrentInterface *load(const QByteArray &data, const QUrl &url, const QString &group, const QString &savedir) = 0;

    /**
     * Load a torrent using a byte array silently
     * @param data Data of the torrent
     * @param url URL of the torrent
     * @param group Group to use
     * @param savedir Directory to save to
     * @return The loaded TorrentInterface or 0 on failure
     */
    virtual bt::TorrentInterface *loadSilently(const QByteArray &data, const QUrl &url, const QString &group, const QString &savedir) = 0;

    /**
     * Remove a download.This will delete all temp
     * data from this TorrentControl And delete the
     * TorrentControl itself. It can also potentially
     * start a new download (when one is waiting to be downloaded).
     * @param tc The torrent
     * @param data_to Whether or not to delete the file data to
     */
    virtual void remove(bt::TorrentInterface *tc, bool data_to) = 0;

    /**
     * Remove a list of downloads.
     * @param todo The torrent list
     * @param data_to Whether or not to delete the file data to
     */
    virtual void remove(QList<bt::TorrentInterface *> &todo, bool data_to) = 0;

    /**
     * Find the next free torX dir.
     * @return Path to the dir (including the torX part)
     */
    virtual QString findNewTorrentDir() const = 0;

    /**
     * Load an existing torrent, which has already a properly set up torX dir.
     * @param tor_dir The torX dir
     */
    virtual void loadExistingTorrent(const QString &tor_dir) = 0;

    /**
     * Sets global suspended state for all torrents (QueueManager) and stopps all torrents.
     * No torrents will be automatically started/stopped.
     */
    virtual void setSuspendedState(bool suspend) = 0;

    /// Gets the globla suspended state
    virtual bool getSuspendedState() = 0;

    /// Get the QueueManager
    virtual kt::QueueManager *getQueueManager() = 0;

    /// Get the GroupManager
    virtual kt::GroupManager *getGroupManager() = 0;

    /// Get the MagnetManager
    virtual kt::MagnetManager *getMagnetManager() = 0;

    /// Get a pointer to the external interface object (for dbus and scripting)
    virtual DBus *getExternalInterface() = 0;

    /// Apply all settings
    virtual void applySettings() = 0;

    /// Load a magnet link
    virtual void load(const bt::MagnetLink &mlink, const MagnetLinkLoadOptions &options) = 0;

    /// Create a torrent (Note: hash calculation should be finished, and torrent should have been saved)
    virtual bt::TorrentInterface *createTorrent(bt::TorrentCreator *tc, bool seed) = 0;

Q_SIGNALS:
    /**
     * A bt::TorrentInterface was added
     * @param tc
     */
    void torrentAdded(bt::TorrentInterface *tc);

    /**
     * A TorrentInterface was removed
     * @param tc
     */
    void torrentRemoved(bt::TorrentInterface *tc);

    /**
     * A TorrentInterface has finished downloading.
     * @param tc
     */
    void finished(bt::TorrentInterface *tc);

    /**
     * Torrent download is stopped by error
     * @param tc TorrentInterface
     * @param msg Error message
     */
    void torrentStoppedByError(bt::TorrentInterface *tc, QString msg);

    /**
     * Signal emmitted when the settings have been changed in the settings dialog.
     * Plugins interested in this should update their internal states.
     * */
    void settingsChanged();
};

}

#endif
