/*
 * Copyright © 2004-2010 Jens Oknelid, paskharen@gmail.com
 *
 * 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.
 *
 * This program 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 <https://www.gnu.org/licenses/>.
 *
 * In addition, as a special exception, compiling, linking, and/or
 * using OpenSSL with this program is allowed.
 */

#pragma once

#include <dcpp/stdinc.h>
#include <dcpp/ConnectionManager.h>
#include <dcpp/DownloadManager.h>
#include <dcpp/LogManager.h>
#include <dcpp/QueueManager.h>
#include <dcpp/TimerManager.h>
#include <dcpp/UploadManager.h>
#include <dcpp/FavoriteManager.h>
#include "entry.hh"
#include "treeview.hh"
#include "transfers.hh"
#include "message.hh"
#include "notify.hh"

class BookEntry;
class Search;

class MainWindow:
        public Entry,
        public dcpp::LogManagerListener,
        public dcpp::QueueManagerListener,
        public dcpp::TimerManagerListener
{
public:
    MainWindow();
    virtual ~MainWindow();

    // Inherited from Entry
    GtkWidget *getContainer();

    // GUI functions
    void show();
    void setTitle(const std::string& text);
    void setUrgent_gui();
    bool isActive_gui();
    void removeBookEntry_gui(BookEntry *entry);
    GtkWidget *currentPage_gui();
    void raisePage_gui(GtkWidget *page);
    static bool getUserCommandLines_gui(const std::string &command, dcpp::StringMap &ucParams);
    void propertiesMagnetDialog_gui(std::string magnet);
    void showMessageDialog_gui(const std::string primaryText, const std::string secondaryText);
    void showDownloadQueue_gui();
    void showFavoriteHubs_gui();
    void showFavoriteUsers_gui();
    void showFinishedDownloads_gui();
    void showFinishedUploads_gui();
    void showHub_gui(std::string address, std::string encoding = "");
    void showSearchSpy_gui();
    void showSearchADL_gui();
    void showCmdDebug_gui();
    void showUploadQueue_gui();
    void addPrivateMessage_gui(Msg::TypeMsg typemsg, std::string cid, std::string hubUrl = "", std::string message = "", bool useSetting = false);
    void addPrivateStatusMessage_gui(Msg::TypeMsg typemsg, std::string cid, std::string message = "");
    void showPublicHubs_gui();
    void showShareBrowser_gui(dcpp::UserPtr user, std::string file, std::string dir, bool useSetting);
    Search *addSearch_gui();
    void addSearch_gui(std::string magnet);
    void actionMagnet_gui(std::string magnet);
    void setMainStatus_gui(std::string text, time_t t = time(NULL));
    void showNotification_gui(std::string head, std::string body, Notify::TypeNotify notify);
    GtkWidget* getChooserDialog_gui();
    void fileToDownload_gui(std::string magnet, std::string path);
    void parsePartial_gui(dcpp::HintedUser aUser, std::string txt);

    // Client functions
    void openOwnList_client(bool useSetting);
    void matchAllList_client();
    void updateFavoriteHubMenu_client(const dcpp::FavoriteHubEntryList &fh);

private:
    typedef std::pair<std::string, std::string> ParamPair;
    typedef std::vector<ParamPair> ListParamPair;

    // GUI functions
    void loadIcons_gui();
    void showTransfersPane_gui();
    void autoOpen_gui();
    void addTabMenuItem_gui(GtkWidget* menuItem, GtkWidget* page);
    void removeTabMenuItem_gui(GtkWidget *menuItem);
    void addBookEntry_gui(BookEntry *entry);
    void previousTab_gui();
    void nextTab_gui();
    void onSwitchOnPage_gui(int pageNum);
    BookEntry *findBookEntry(const EntryType type, const std::string &id = "");
    void createStatusIcon_gui();
    void updateStatusIconTooltip_gui(std::string download, std::string upload);
    void setStats_gui(std::string hubs, std::string downloadSpeed,
                      std::string downloaded, std::string uploadSpeed, std::string uploaded);
    void setToolbarButton_gui();
    void setTabPosition_gui(int position);
    void setToolbarStyle_gui(int style);
    void removeTimerSource_gui();
    void setChooseMagnetDialog_gui();
    void showMagnetDialog_gui(const std::string &magnet, const std::string &name, const int64_t size,
                              const std::string &tth);
    void showPortsError(const std::string& port);
    void setToolbarMenu_gui(const std::string &item_key, const std::string &button_key, const std::string &key);
    void updateFavoriteHubMenu_gui(ListParamPair list);
    void checkToolbarMenu_gui();
    void updateFreespaceBar_gui(std::string freespace, float freepercent);

    // GUI Callbacks
    static gboolean onWindowState_gui(GtkWidget *widget, GdkEventWindowState *event, gpointer data);
    static gboolean onFocusIn_gui(GtkWidget *widget, GdkEventFocus *event, gpointer data);
    static gboolean onCloseWindow_gui(GtkWidget *widget, GdkEvent *event, gpointer data);
    static gboolean onKeyPressed_gui(GtkWidget *widget, GdkEventKey *event, gpointer data);
    static gboolean onButtonReleasePage_gui(GtkWidget *widget, GdkEventButton *event, gpointer data);
    static gboolean animationStatusIcon_gui(gpointer data);
    static void onSizeWindowState_gui(GtkWidget* widget,GtkAllocation *allocation,gpointer data);
    static void onRaisePage_gui(GtkMenuItem *item, gpointer data);
    static void onPageSwitched_gui(GtkNotebook *notebook, GtkWidget *page, guint num, gpointer data);
    static void onPaneRealized_gui(GtkWidget *pane, gpointer data);
    static void onConnectClicked_gui(GtkWidget *widget, gpointer data);
    static void onFavoriteHubsClicked_gui(GtkWidget *widget, gpointer data);
    static void onFavoriteUsersClicked_gui(GtkWidget *widget, gpointer data);
    static void onPublicHubsClicked_gui(GtkWidget *widget, gpointer data);
    static void onPreferencesClicked_gui(GtkWidget *widget, gpointer data);
    static void onHashClicked_gui(GtkWidget *widget, gpointer data);
    static void onSearchClicked_gui(GtkWidget *widget, gpointer data);
    static void onSearchADLClicked_gui(GtkWidget *widget, gpointer data);
    static void onSearchSpyClicked_gui(GtkWidget *widget, gpointer data);
    static void onDownloadQueueClicked_gui(GtkWidget *widget, gpointer data);
    static void onFinishedDownloadsClicked_gui(GtkWidget *widget, gpointer data);
    static void onFinishedUploadsClicked_gui(GtkWidget *widget, gpointer data);
    static void onQuitClicked_gui(GtkWidget *widget, gpointer data);
    static void onOpenFileListClicked_gui(GtkWidget *widget, gpointer data);
    static void onOpenOwnListClicked_gui(GtkWidget *widget, gpointer data);
    static void onMatchAllList_gui(GtkWidget *widget, gpointer data);
    static void onRefreshFileListClicked_gui(GtkWidget *widget, gpointer data);
    static void onReconnectClicked_gui(GtkWidget *widget, gpointer data);
    static void onCloseClicked_gui(GtkWidget *widget, gpointer data);
    static void onPreviousTabClicked_gui(GtkWidget* widget, gpointer data);
    static void onNextTabClicked_gui(GtkWidget* widget, gpointer data);
    static void onAboutClicked_gui(GtkWidget *widget, gpointer data);
    //static void onAboutDialogActivateLink_gui(GtkAboutDialog *dialog, const gchar *link, gpointer data);
    static void onCloseBookEntry_gui(GtkWidget *widget, gpointer data);
    static void onStatusIconActivated_gui(GtkStatusIcon *statusIcon, gpointer data);
    static void onStatusIconPopupMenu_gui(GtkStatusIcon *statusIcon, guint button, guint time, gpointer data);
    static void onStatusIconBlinkUseToggled_gui(GtkWidget *widget, gpointer data);
    static void onShowInterfaceToggled_gui(GtkCheckMenuItem *item, gpointer data);
    static void onLinkClicked_gui(GtkWidget *widget, gpointer data);
    static void onTransferToggled_gui(GtkWidget *widget, gpointer data);
    static void onBrowseMagnetButton_gui(GtkWidget *widget, gpointer data);
    static void onDowloadQueueToggled_gui(GtkWidget *widget, gpointer data);
    static void onSearchMagnetToggled_gui(GtkWidget *widget, gpointer data);
    static void onSetMagnetChoiceDialog_gui(GtkWidget *widget, gpointer data);
    static void onResponseMagnetDialog_gui(GtkWidget *dialog, gint response, gpointer data);
    static gboolean onDeleteEventMagnetDialog_gui(GtkWidget *dialog, GdkEvent *event, gpointer data);
    static gboolean onMenuButtonClicked_gui(GtkWidget *widget, gpointer data);
    static gboolean onAddButtonClicked_gui(GtkWidget *widget, gpointer data);
    static void menuPosition_gui(GtkMenu *menu, gint *x, gint *y, gboolean *push, gpointer data);
    static void onToolToggled_gui(GtkWidget *widget, gpointer data);
    static void onTopToolbarToggled_gui(GtkWidget *widget, gpointer data);
    static void onLeftToolbarToggled_gui(GtkWidget *widget, gpointer data);
    static void onHideToolbarToggled_gui(GtkWidget *widget, gpointer data);
    static void onSizeToolbarToggled_gui(GtkWidget *widget, gpointer data);
    static void onHubClicked_gui(GtkWidget *widget, gpointer data);
    static void onTTHFileDialog_gui(GtkWidget *widget, gpointer data);
    static void onTTHFileButton_gui(GtkWidget *widget, gpointer data);
    static void onDebugCMD(GtkWidget *widget, gpointer data);
    static void onFreeSpaceBar(GtkWidget *widget, gpointer data);
    static void onUploadQueueClicked_gui(GtkWidget *widget, gpointer data);
    /**/
    static void onCloseAllHub_gui(GtkWidget *widget, gpointer data);
    static void onCloseAllPM_gui(GtkWidget *widget, gpointer data);
    static void onCloseAllSearch_gui(GtkWidget *widget, gpointer data);
    static void onCloseAlloffPM_gui(GtkWidget *widget, gpointer data);
    static void onReconectAllHub_gui(GtkWidget *widget, gpointer data);

    // Client functions
    void autoConnect_client();
    void startSocket_client(bool changed);
    void refreshFileList_client();
    void addFileDownloadQueue_client(std::string name, int64_t size, std::string tth);

    // Client callbacks
    virtual void on(dcpp::LogManagerListener::Message, time_t t, const std::string &m) noexcept;
    virtual void on(dcpp::QueueManagerListener::Finished, dcpp::QueueItem *item, const std::string& dir, int64_t avSpeed) noexcept;
    virtual void on(dcpp::TimerManagerListener::Second, uint64_t ticks) noexcept;
    virtual void on(dcpp::QueueManagerListener::PartialList, const dcpp::HintedUser& aUser, const std::string& text) noexcept;

    GtkWindow *window;
    gint current_width, current_height;
    gboolean is_maximized;
    Transfers* transfers;
    GtkStatusIcon *statusIcon;
    int64_t lastUpdate, lastUp, lastDown;
    bool minimized;
    dcpp::StringList EntryList;
    guint timer;
    int statusFrame;
    bool bUseStatusIconBlink;
    bool onQuit;
    int ToolbarStyle;
};
