/*
 * Copyright (C) 2014-2026 CZ.NIC
 *
 * 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 3 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 <http://www.gnu.org/licenses/>.
 *
 * In addition, as a special exception, the copyright holders give
 * permission to link the code of portions of this program with the
 * OpenSSL library under certain conditions as described in each
 * individual source file, and distribute linked combinations including
 * the two.
 */

#pragma once

#include <QDialog>
#include <QList>
#include <QMenu>
#include <QSet>
#include <QSortFilterProxyModel>

#include "src/models/action_list_model.h"
#include "src/models/combo_box_model.h"

/*!
 * @brief Top tool bar configuration dialogue.
 */
namespace Ui {
	class DlgToolBar;
}

class QAction; /* Forward declaration. */
class QMenu; /* Forward declaration. */
class QMenuBar; /* Forward declaration. */
class QToolBar; /* Forward declaration. */

class DlgToolBar : public QDialog {
	Q_OBJECT

public:
	/*!
	 * @brief Tool bar position/function.
	 */
	enum Position {
		MAIN_TOP, /*!< Main window top toolbar. */
		ACCOUNT, /*!< Main window account tool bar. */
		MESSAGE, /*!< Main window message tool bar. */
		DETAIL, /*!< Main window detail tool bar. */
		ATTACHMENT /*!< Main window attachment toolbar. */
	};

private:
	/*!
	 * @brief Constructor.
	 *
	 * @param[in] menuBar Menu bar for actions.
	 * @param[in] unlistedInMenu Actions not listed in menu bar.
	 * @param[in] excluded Actions ignored by this dialogue.
	 * @param[in] position Tool bar position.
	 * @param[in] toolBar Tool bar to insert actions into.
	 * @param[in] afterUnconfigurableToolbarElement Tool bar action after which to start.
	 * @param[in] beforeUnconfigurableToolbarElement Tool bar action before which to stop.
	 * @param[in] defaultToolBarActions Default tool bar actions.
	 * @param[in] parent Parent object.
	 */
	explicit DlgToolBar(const QMenuBar *menuBar,
	    const QList<QAction *> &unlistedInMenu,
	    const QSet<QAction *> &excluded, enum Position position,
	    QToolBar *toolBar, QAction *afterUnconfigurableToolbarElement,
	    QAction *beforeUnconfigurableToolbarElement,
	    const QList<QAction *> &defaultToolBarActions,
	    QWidget *parent = Q_NULLPTR);

public:
	/*!
	 * @brief Destructor.
	 */
	~DlgToolBar(void);

	/*!
	 * @brief View tool bar configure dialogue.
	 *
	 * @param[in] menuBar Menu bar for actions.
	 * @param[in] unlistedInMenu Actions not listed in menu bar.
	 * @param[in] excluded Actions ignored by this dialogue.
	 * @param[in] position Tool bar position.
	 * @param[in] toolBar Tool bar to insert actions into.
	 * @param[in] afterUnconfigurableToolbarElement Tool bar action after which to start.
	 * @param[in] beforeUnconfigurableToolbarElement Tool bar action before which to stop.
	 * @param[in] defaultToolBarActions Default tool bar actions.
	 * @param[in] parent Parent object.
	 * @return True when dialogue has been accepted.
	 */
	static
	bool configureToolBar(const QMenuBar *menuBar,
	    const QList<QAction *> &unlistedInMenu,
	    const QSet<QAction *> &excluded, enum Position position,
	    QToolBar *toolBar, QAction *afterUnconfigurableToolbarElement,
	    QAction *beforeUnconfigurableToolbarElement,
	    const QList<QAction *> &defaultToolBarActions,
	    QWidget *parent = Q_NULLPTR);

private slots:
	/*!
	 * @brief Apply filter text on the table.
	 *
	 * @param[in] text Filter text.
	 */
	void filterFound(const QString &text);

	/*!
	 * @brief Load list of available operations.
	 *
	 * @param[in] availableMenuIndex Index of menu selection combo box.
	 */
	void loadAvailableOperations(int availableMenuIndex);

	/*!
	 * @brief Activate/deactivate buttons on available selection change.
	 */
	void handleAvailableSelectionChange(void);

	/*!
	 * @brief Activate/deactivate buttons on assigned selection change.
	 */
	void handleAssignedSelectionChange(void);

	/*!
	 * @brief Assign selected action(s) to tool bar.
	 */
	void assignSelectedAvailableOperations(void);

	/*!
	 * @brief Remove selected action(s) from tool bar.
	 */
	void removeSelectedAssignedOperations(void);

	/*!
	 * @brief Change tool bar button style according to radio button selection.
	 *
	 * @param[in] checked True if button checked.
	 */
	void radioButtonsToggled(bool checked);

	/*!
	 * @brief Assign/remove checked/unchecked actions to/from tool bar.
	 *
	 * @param[in] topLeft Top left model index.
	 * @param[in] bottomRight Bottom right model index.
	 * @param[in] roles Roles.
	 */
	void handleAssignedDataChange(const QModelIndex &topLeft,
	    const QModelIndex &bottomRight, const QVector<int> &roles);

	/*!
	 * @brief Move actions across toolbar according to model changes.
	 *
	 * @param[in] parent Parent object.
	 * @param[in] start Start position.
	 * @param[in] end End position.
	 * @param[in] destination Destination index.
	 * @param[in] row Row.
	 */
	void assignedRowsMoved(const QModelIndex &parent, int start, int end,
	    const QModelIndex &destination, int row);

	/*!
	 * @brief Group and move selection one above the selected top element.
	 */
	void moveSelectedAssignedOperationsUp(void);

	/*!
	 * @brief Group and move selection one below the selected bottom element.
	 */
	void moveSelectedAssignedOperationsDown(void);

	/*!
	 * @brief Insert separator to tool bar.
	 */
	void insertSeparator(void);

	/*!
	 * @brief Reset to defaults.
	 */
	void resetDefaults(void);

private:
	/*!
	 * @brief Initialises the dialogue.
	 */
	void initDlg(void);

	/*!
	 * @brief Set icon set to buttons.
	 */
	void setIcons(void);

	/*!
	 * @brief Used to remove selected action(s) from tool bar via event filter.
	 *
	 * @param[in] dlgPtr Pointer to this dialogue.
	 */
	static
	void removeSelectedAssignedOperationsViaFilter(QObject *dlgPtr);

	Ui::DlgToolBar *m_ui;

	QMenu m_dummyMenu; /*!< Menu for additional actions. */
	QSet<QAction *> m_excludedActions; /*!< Actions that aren't offered. */

	enum Position m_position;  /*!< Tool bar position.*/
	QToolBar *m_toolBar; /*!< Tool bar to insert actions into. */
	QAction *m_afterUnconfigurableToolbarElement; /*!< Tool bar action after which to start. */
	QAction *m_beforeUnconfigurableToolbarElement; /*!< Tool bar action before which to stop. */
	QList<QAction *> m_defaultToolBarActions; /*!< Default tool bar actions. */

	CBoxModel m_availableMenuModel; /*!< Menu model. */
	QList<QMenu *> m_availableMenus; /*!< Available action menus. */

	QSortFilterProxyModel m_availableOperationsProxyModel; /*!< User for content sorting. */
	QString m_dfltFilerLineStyleSheet; /*!< Used to remember default line edit style. */

	ActionListModel m_availableOperationsModel; /*!< Available action list model. */
	ActionListModel m_assignedOperationsModel; /*!< Assigned action list model. */
};

/*!
 * @brief Insert actions into tool bar before given action.
 *
 * @param[in] toolBar Tool bar to insert actions into.
 * @param[in] actionList List of actions, null values are treated as separators.
 * @param[in] before Action before which to insert.
 */
void insertToolBarActions(QToolBar *toolBar,
    const QList<QAction *> &actionList, QAction *before = Q_NULLPTR);

/*!
 * @brief Insert stored actions into tool bar before given action.
 *
 * @param[in] actionParent Object holding children among which to search for actions.
 * @param[in] position Tool bar position.
 * @param[in] toolBar Tool bar to insert actions into.
 * @param[in] actionList List of actions, null values are treated as separators.
 * @param[in] before Action before which to insert.
 */
void loadToolBarActions(QObject *actionParent,
    enum DlgToolBar::Position position, QToolBar *toolBar,
    const QList<QAction *> &dfltActionList, QAction *before = Q_NULLPTR);

/*!
 * @brief Get tool bar button style from preferences.
 *
 * @param[in] position Tool bar position.
 * @return Tool bar button style value.
 */
Qt::ToolButtonStyle toolBarButtonStyle(enum DlgToolBar::Position position);
