/*
 * Copyright 2014 Mihai Niculescu <q.quark@gmail.com>
 *
 * This file is part of EqualX Project (https://launchpad.net/equalx/)
 *
 * EqualX 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 3 of the License, or
 * (at your option) any later version.
 *
 * EqualX 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef LIBRARY_H
#define LIBRARY_H

#include <QObject>
#include <QSqlDatabase>

#include "LibraryData.h"

class LibraryManager : public QObject
{
    Q_OBJECT
public:
    enum SEARCH_MODE{
        SEARCH_BY_TITLE_DESCRIPTION,
        SEARCH_BY_TITLE,
        SEARCH_BY_DESCRIPTION,
        SEARCH_BY_CONTENT
    };

    static LibraryManager* Instance();

    QString errorStr() const {return mErrStr;}

    /*  Add an equation with 'title' and 'description' in bookmarks
     * which its parent is specified by 'parentId'. If successful,
     * it copies the file 'file' to the folder which is represented
     * in the database by 'parentId'. If 'parentId'= 1, then its
     * parent is the root node.
     *
     * If everything went well, it returns the id of the equation in DB.
     * If not it returns -1;
     */
    int  addBookmark(const QString& title, const QString& description, const QString& file, int parentId=1);
    int  addBookmark(const Bookmark& bookmark, int parentId=1);
    /*  Add a folder to bookmarks in database. If successful, create
     * a subfolder to the folder which has id. If 'parentId'= 1, then its
     * parent is the root node.
     *
     * If everything went well it returns the id of the folder in DB
     * If not it returns -1;
     */
    int  addBookmarkFolder(const QString& name, const QString& description=QString(""), int parentId=1);
    int  addBookmarkFolder(const BookmarkFolder& folder, int parentId=1);

    /*  Add an equation specified by 'title' and 'file' in history. If successful,
     * it copies the file 'file' to history folder.
     *
     * If everything went well, it returns the id of the equation in history.
     * If not it returns -1;
     */
    int addHistoryItem(const QString& title, const QString& file);

    LibraryRowsList getAllHistory();
    const HistoryRow getHistoryRow(int id);


    Bookmark getBookmark(int id);
    BookmarkFolder getBookmarkFolder(int id);

    // returns a list with all children (all bookmarks and subfolders) contained in parent folder
    LibraryRowsList getChildren(int idparent=1);

    // returns a list with all folders in bookmarks
    LibraryRowsList getAllBookmarkedFolders();

    int childrenCountInFolder(int id=1); // returns the direct number of children of folder (subfolders+bookmarks)

    int historySize(); // returns the number of items in history

    // copy bookmark with id 'id' to folder with id 'idparent'
    // returns the new copied bookmark
    Bookmark copyBookmark(int id, int idparent=1);

    // copy folder (including all subnodes) with 'id' to folder 'idparent'
    // returns the new copied folder
    BookmarkFolder copyBookmarkFolder(int id, int idparent=1);

    /* Move Actions */
    // these will emit 2 bookmarkFolderChanged() signals:
    // one for the old folder, second for the new folder
    bool moveData(const LibraryModelData& data, int newParentId);
    bool moveBookmark(int id, int newParentId);
    bool moveBookmarkFolder(int id, int newParentId);

    /* Update fields (no reparenting) */
    bool updateData(const LibraryModelData& data);
    bool updateBookmark(const Bookmark &bookmark);
    bool updateBookmarkFolder(const BookmarkFolder &folder);

    /* Remove Actions */
    bool removeBookmark(int id);
    bool removeBookmarkFolder(int id);

    // returns the absolute path to the root library directory
    QString path() const;

    LibraryRowsList searchBookmarks(QString searchText, SEARCH_MODE searchType=SEARCH_BY_TITLE_DESCRIPTION);
public slots:
    bool clearHistory();

signals:
    void bookmarkAdded(const Bookmark &);
    void bookmarksChanged();
    void bookmarkFolderChanged(const QString& dirPath);
    void historyChanged();
    void historyChanged(const HistoryRow &);

private:
    explicit LibraryManager(QObject *parent = 0);
    LibraryManager(LibraryManager const&);             // copy constructor not implemented
    LibraryManager& operator=(LibraryManager const&);  // assignment operator not implemented
    virtual ~LibraryManager();

    bool setup();
    bool createLibrary(const QString& path);
    bool createDatabaseTablesFromFile(const QString& sqlFile);

    int lastId(const QString& tableName);
    bool removeSystemDir(const QString& dirName); // removes a system directory recursively
    bool removeBookmarkFromFS(int id, const QString &filetype);

    void copyChildren(int ofFolderId, int toNewFolderId);
protected:
    QSqlDatabase mDB;
    QString mErrStr; // error string
    QString mBookmarksDirStr; // absolute path to the library dir
    QString mHistoryDirStr; // absolute path to history dir

private:
    static LibraryManager* mInstance;
};

#endif // LIBRARY_H
