/*
 * 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.
 */

#include <QAction>
#include <QLineEdit>
#include <QListView>
#include <QPushButton>
#include <QVBoxLayout>

#include "src/delegates/tag_item.h"
#include "src/identifiers/message_id.h"
#include "src/json/tag_entry.h"
#include "src/views/table_home_end_filter.h"
#include "src/views/table_space_selection_filter.h"
#include "src/views/table_tab_ignore_filter.h"
#include "src/widgets/tags_popup_control_widget.h"

#define LAYOUT_MARGIN_PX 3

TagsPopupControlWidget::TagsPopupControlWidget(TagContainer *tagCont,
    QAction *actionEditAvailableTags, QWidget *parent)
    : QWidget(parent),
    m_dfltFilerLineStyleSheet(SortFilterProxyModel::invalidFilterEditStyle),
    m_tagsDelegate(this),
    m_tagAssignmentModel(tagCont, this),
    m_tagListProxyModel(this),
    m_filterLine(Q_NULLPTR),
    m_tagListView(Q_NULLPTR),
    m_manageTagsButton(Q_NULLPTR),
    m_actionEditAvailableTags(actionEditAvailableTags)
{
	TagsPopupControlWidget *m_tagsPopup = this;

	m_tagsPopup->setObjectName(QString::fromUtf8("m_tagsPopup"));
	m_tagsPopup->setWindowFlags(Qt::Widget | Qt::Popup);

	m_filterLine = new (::std::nothrow) QLineEdit(m_tagsPopup);
	if (Q_NULLPTR != m_filterLine) {
		m_filterLine->setObjectName("m_filterLine");

		m_filterLine->setToolTip(tr("Enter sought expression."));
		m_filterLine->setPlaceholderText(tr("Filter"));
		m_filterLine->setClearButtonEnabled(true);

		connect(m_filterLine, SIGNAL(textChanged(QString)),
		    m_tagsPopup, SLOT(filterTags(QString)));
	}

	m_tagListView = new (::std::nothrow) QListView(m_tagsPopup);
	if (Q_NULLPTR != m_tagListView) {
		m_tagListView->setObjectName(QString::fromUtf8("m_tagListView"));

		m_tagListView->setSelectionMode(QAbstractItemView::NoSelection);

		m_tagListView->setItemDelegate(&m_tagsDelegate);
		m_tagListProxyModel.setSourceModel(&m_tagAssignmentModel);
		m_tagListProxyModel.setSortRole(TagAssignmentModel::ROLE_PROXYSORT);
		m_tagListView->setModel(&m_tagListProxyModel);
		m_tagListView->setSelectionMode(QAbstractItemView::NoSelection);
		m_tagListView->setSelectionBehavior(QAbstractItemView::SelectRows);

		m_tagListView->installEventFilter(
		    new (::std::nothrow) TableHomeEndFilter(m_tagListView));
		m_tagListView->installEventFilter(
		    new (::std::nothrow) TableSpaceSelectionFilter(
		        TagAssignmentModel::COL_TAG_NAME, m_tagListView));
		m_tagListView->installEventFilter(
		    new (::std::nothrow) TableTabIgnoreFilter(m_tagListView));
	}

	if (Q_NULLPTR != m_actionEditAvailableTags) {
		m_manageTagsButton = new (::std::nothrow) QPushButton(m_tagsPopup);
		if (Q_NULLPTR != m_manageTagsButton) {
			m_manageTagsButton->setObjectName(QString::fromUtf8("m_manageTagsButton"));

			m_manageTagsButton->setIcon(m_actionEditAvailableTags->icon());
			m_manageTagsButton->setText(m_actionEditAvailableTags->text());
			m_manageTagsButton->setToolTip(m_actionEditAvailableTags->toolTip());

			connect(m_manageTagsButton, SIGNAL(clicked()),
			   m_tagsPopup, SLOT(manageTagsClicked()));
		}
	}

	QVBoxLayout *verticalLayout = Q_NULLPTR;

	verticalLayout = new (::std::nothrow) QVBoxLayout(m_tagsPopup);
	if (Q_NULLPTR != verticalLayout) {
		verticalLayout->setObjectName(QString::fromUtf8("verticalLayout"));

		verticalLayout->setContentsMargins(
		    LAYOUT_MARGIN_PX, LAYOUT_MARGIN_PX,
		    LAYOUT_MARGIN_PX, LAYOUT_MARGIN_PX);

		verticalLayout->addWidget(m_filterLine);

		verticalLayout->addWidget(m_tagListView);

		verticalLayout->addWidget(m_manageTagsButton);

		QWidget::setTabOrder(m_filterLine, m_tagListView);
		QWidget::setTabOrder(m_tagListView, m_manageTagsButton);
	}
}

QSize TagsPopupControlWidget::sizeHint(void) const
{
	static TagItem tagItem;
	if (Q_UNLIKELY(!tagItem.isValid())) {
		Json::TagEntry tagEntry(1,
		    "Quite long tag name used for size estimation", "abcdef",
		    "");
		tagItem = TagItem(tagEntry);
	}

	QSize sizeHint = tagItem.sizeHint(QStyleOptionViewItem());
	int viewItemWidth = sizeHint.width() + 40; // 40 for borders etc.
	int viewItemHeight = sizeHint.height() * 16; // 16 times the height of list entry

	return QSize(viewItemWidth, viewItemHeight);
}

void TagsPopupControlWidget::setMsgIds(const AcntId &acntId,
    const QSet<MsgId> &msgIds)
{
	QSet<qint64> dmIds;
	for (const MsgId &msgId : msgIds) {
		dmIds.insert(msgId.dmId());
	}
	m_tagAssignmentModel.setMsgIds(acntId, dmIds);

	if (dmIds.isEmpty()) {
		m_tagListView->setSelectionMode(QAbstractItemView::NoSelection);
		m_tagListView->setSelectionBehavior(QAbstractItemView::SelectRows);
	} else {
		m_tagListView->setSelectionMode(QAbstractItemView::SingleSelection);
		m_tagListView->setSelectionBehavior(QAbstractItemView::SelectRows);
	}
}

void TagsPopupControlWidget::filterTags(const QString &text)
{
	/* Store style at first invocation. */
	if (m_dfltFilerLineStyleSheet == SortFilterProxyModel::invalidFilterEditStyle) {
		m_dfltFilerLineStyleSheet = m_filterLine->styleSheet();
	}

#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
	m_tagListProxyModel.setFilterRegularExpression(
	    QRegularExpression(QRegularExpression::escape(text),
	        QRegularExpression::CaseInsensitiveOption));
#else /* < Qt-5.15 */
	m_tagListProxyModel.setFilterRegExp(QRegExp(text,
	    Qt::CaseInsensitive, QRegExp::FixedString));
#endif /* >= Qt-5.15 */
	/* Set filter field background colour. */
	if (text.isEmpty()) {
		m_filterLine->setStyleSheet(m_dfltFilerLineStyleSheet);
	} else if (m_tagListProxyModel.rowCount() != 0) {
		m_filterLine->setStyleSheet(
		    SortFilterProxyModel::foundFilterEditStyle);
	} else {
		m_filterLine->setStyleSheet(
		    SortFilterProxyModel::notFoundFilterEditStyle);
	}
}

void TagsPopupControlWidget::manageTagsClicked(void)
{
	if (Q_NULLPTR != m_actionEditAvailableTags) {
		m_actionEditAvailableTags->trigger();
	}

	Q_EMIT controlClosed();

	close();
}
