/* This file is part of the KDE project

   Copyright (C) 2008 Lukas Appelhans <l.appelhans@gmx.de>

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

#include <diskio/cache.h>
#include <interfaces/cachefactory.h>

#include <KIO/Job>

#include <QByteArray>
#include <QString>

class QStringList;
class KJob;

namespace bt
{
class Torrent;
class TorrentFile;
class Chunk;
class PreallocationThread;
}

using namespace bt;

class BTCache : public QObject, public bt::Cache
{
    Q_OBJECT
public:
    BTCache(bt::Torrent &tor, const QString &tmpdir, const QString &datadir);
    ~BTCache();

    /**
     * Load the file map of a torrent.
     * If it doesn't exist, it needs to be created.
     */
    virtual void loadFileMap()
    {
    }

    /**
     * Save the file map of a torrent
     */
    virtual void saveFileMap()
    {
    }

    /**
     * Get the actual output path.
     * @return The output path
     */
    virtual QString getOutputPath() const
    {
        return QString();
    }

    /**
     * Changes the tmp dir. All data files should already been moved.
     * This just modifies the tmpdir variable.
     * @param ndir The new tmpdir
     */
    virtual void changeTmpDir(const QString &ndir)
    {
        Q_UNUSED(ndir)
    }

    /**
     * Changes output path. All data files should already been moved.
     * This just modifies the datadir variable.
     * @param outputpath New output path
     */
    virtual void changeOutputPath(const QString &outputpath)
    {
        Q_UNUSED(outputpath)
    }

    /**
     * Move the data files to a new directory.
     * @param ndir The directory
     * @return The job doing the move
     */
    virtual KJob *moveDataFiles(const QString &ndir)
    {
        return nullptr;
    }

    /**
     * A move of a bunch of data files has finished
     * @param job The job doing the move
     */
    virtual void moveDataFilesFinished(KJob *job)
    {
        Q_UNUSED(job)
    }

    /**
     * Load a chunk into memory. If something goes wrong,
     * an Error should be thrown.
     * @param c The Chunk
     */
    virtual void load(Chunk *c);

    /**
     * Save a chunk to disk. If something goes wrong,
     * an Error should be thrown.
     * @param c The Chunk
     */
    virtual void save(Chunk *c);

    /**
     * Prepare a chunk for downloading.
     * @param c The Chunk
     * @return true if ok, false otherwise
     */
    virtual bool prep(Chunk *c);

    /**
     * Create all the data files to store the data.
     */
    virtual void create()
    {
    }

    /**
     * Close the cache file(s).
     */
    virtual void close()
    {
    }

    /**
     * Open the cache file(s)
     */
    virtual void open()
    {
    }

    /// Does nothing, can be overridden to be alerted of download status changes of a TorrentFile
    virtual void downloadStatusChanged(TorrentFile *, bool)
    {
    }

    /**
     * Preallocate diskspace for all files
     * @param prealloc The thread doing the preallocation
     */
    virtual void preallocateDiskSpace(PreallocationThread *prealloc)
    {
        Q_UNUSED(prealloc)
    }

    /**
     * Test all files and see if they are not missing.
     * If so put them in a list
     */
    virtual bool hasMissingFiles(QStringList &sl)
    {
        return false;
    } // We never have missing files, cause we don't have files :P

    /**
     * Delete all data files, in case of multi file torrents
     * empty directories should also be deleted.
     */
    virtual KJob *deleteDataFiles()
    {
        return nullptr;
    } // TODO: Implement!!!
    virtual bt::PieceData *loadPiece(bt::Chunk *, bt::Uint32, bt::Uint32)
    {
        return nullptr;
    }
    virtual bt::PieceData *preparePiece(bt::Chunk *, bt::Uint32, bt::Uint32)
    {
        return nullptr;
    }
    virtual void savePiece(bt::PieceData *)
    {
    }

    /**
     * Get the number of bytes all the files of this torrent are currently using on disk.
     * */
    virtual Uint64 diskUsage()
    {
        return 0;
    }; // We always use 0 Bytes on HDD, cause we don't write to HDD

Q_SIGNALS:
    void dataArrived(const KIO::fileoffset_t &offset, const QByteArray &data);

private:
    Torrent *m_tor;
};

class BTCacheFactory : public QObject, public CacheFactory
{
    Q_OBJECT
public:
    BTCacheFactory()
    {
    }
    ~BTCacheFactory()
    {
    }

    virtual Cache *create(Torrent &tor, const QString &tmpdir, const QString &datadir);

Q_SIGNALS:
    void cacheAdded(BTCache *cache);
};

#endif
