//=============================================================================
//
//   File : CustomizeToolBarsDialog.cpp
//   Creation date : Wed 01 Dec 2004 14:42:20 by Szymon Stefanek
//
//   This file is part of the KVIrc IRC client distribution
//   Copyright (C) 2004-2010 Szymon Stefanek <pragma at kvirc dot net>
//
//   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, write to the Free Software Foundation,
//   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
//=============================================================================

#include "CustomizeToolBarsDialog.h"

#include "KviApplication.h"
#include "KviActionDrawer.h"
#include "KviLocale.h"
#include "KviMainWindow.h"
#include "KviIconManager.h"
#include "KviActionManager.h"
#include "KviCustomToolBar.h"
#include "KviCustomToolBarManager.h"
#include "KviCustomToolBarDescriptor.h"
#include "KviImageDialog.h"
#include "KviFileUtils.h"
#include "KviFileDialog.h"
#include "KviInternalCommand.h"
#include "KviKvsUserAction.h"
#include "KviTalToolTip.h"
#include "kvi_fileextensions.h"

#include <QPushButton>
#include <QLayout>
#include <QApplication>
#include <QLineEdit>
#include <QLabel>
#include <QMessageBox>
#include <QFrame>
#include <QDir>
#include <QTimer>
#include <QEvent>
#include <QSplitter>
#include <QDropEvent>
#include <QMimeData>
#include <QScreen>

CustomizeToolBarsDialog * CustomizeToolBarsDialog::m_pInstance = nullptr;
extern QRect g_rectToolBarEditorDialogGeometry;

TrashcanLabel::TrashcanLabel(QWidget * p)
    : QLabel(p)
{
	setPixmap(*(g_pIconManager->getBigIcon("kvi_bigicon_trashcan.png")));
	KviTalToolTip::add(this, __tr2qs_ctx("Drop here the icons from the toolbars to remove them", "editor"));
	setFrameStyle(QFrame::Sunken | QFrame::WinPanel);
	setAcceptDrops(true);
	setAlignment(Qt::AlignCenter);
	setMinimumSize(40, 40);
	m_uFlashCount = 0;
	m_pFlashTimer = nullptr;
	m_clrOriginal = palette().color(backgroundRole());
	setAutoFillBackground(true); //needed for flashing
	connect(KviActionManager::instance(), SIGNAL(removeActionsHintRequest()), this, SLOT(flash()));
}

TrashcanLabel::~TrashcanLabel()
{
	if(m_pFlashTimer)
	{
		m_pFlashTimer->stop();
		delete m_pFlashTimer;
	}
}

void TrashcanLabel::flash()
{
	m_uFlashCount = 0;
	if(m_pFlashTimer)
		return;
	m_pFlashTimer = new QTimer();
	connect(m_pFlashTimer, SIGNAL(timeout()), this, SLOT(heartbeat()));
	m_pFlashTimer->start(200);
}

void TrashcanLabel::heartbeat()
{
	m_uFlashCount++;
	if(m_uFlashCount % 2)
	{
		QPalette p = palette();
		p.setColor(backgroundRole(), QColor(0, 0, 0));
		setPalette(p);
	}
	else
	{
		QPalette p = palette();
		p.setColor(backgroundRole(), m_clrOriginal);
		setPalette(p);
	}
	update();
	if(m_uFlashCount == 8)
	{
		m_pFlashTimer->stop();
		delete m_pFlashTimer;
		m_pFlashTimer = nullptr;
	}
}

void TrashcanLabel::dropEvent(QDropEvent * e)
{
	if(e->mimeData()->hasText())
		e->acceptProposedAction();
}

void TrashcanLabel::dragEnterEvent(QDragEnterEvent * e)
{
	if(e->mimeData()->hasText())
		e->acceptProposedAction();
}

CustomToolBarPropertiesDialog::CustomToolBarPropertiesDialog(QWidget * p, const QString & szText, const QString & szId, const QString & szLabel, const QString & szIconId)
    : QDialog(p)
{
	m_szId = szId;
	m_szOriginalId = szId;
	m_szLabel = szLabel;

	setWindowTitle(__tr2qs_ctx("Toolbar Properties - KVIrc", "editor"));
	setWindowIcon(QIcon(*(g_pIconManager->getSmallIcon(KviIconManager::ToolBarEditor))));
	setModal(true);

	QGridLayout * g = new QGridLayout(this);

	QLabel * l = new QLabel(szText, this);
	g->addWidget(l, 0, 0, 1, 6);

	l = new QLabel(__tr2qs_ctx("Label", "editor") + ":", this);
	g->addWidget(l, 1, 0);

	m_pLabelEdit = new QLineEdit(this);
	g->addWidget(m_pLabelEdit, 1, 1, 1, 5);
	m_pLabelEdit->setText(szLabel);
	connect(m_pLabelEdit, SIGNAL(textChanged(const QString &)), this, SLOT(labelTextChanged(const QString &)));

	l = new QLabel(__tr2qs_ctx("Icon", "editor") + ":", this);
	g->addWidget(l, 2, 0);

	m_pIconEdit = new QLineEdit(this);
	m_pIconEdit->setReadOnly(true);
	g->addWidget(m_pIconEdit, 2, 1, 1, 4);

	m_pIconButton = new QPushButton(this);
	g->addWidget(m_pIconButton, 2, 5, 1, 1);
	connect(m_pIconButton, SIGNAL(clicked()), this, SLOT(iconButtonClicked()));

	iconSelected(szIconId);

	m_pAdvanced = new QWidget(this);
	QGridLayout * ag = new QGridLayout(m_pAdvanced);

	l = new QLabel(__tr2qs_ctx("ID", "editor") + ":", m_pAdvanced);
	l->setMinimumWidth(100);
	ag->addWidget(l, 0, 0);

	m_pIdEdit = new QLineEdit(m_pAdvanced);
	ag->addWidget(m_pIdEdit, 0, 1);
	ag->setRowStretch(0, 1);

	m_pIdEdit->setText(szId);

	g->addWidget(m_pAdvanced, 3, 0, 1, 6);
	m_pAdvanced->hide();

	m_pLabelEdit->setFocus();

	QPushButton * pb = new QPushButton(__tr2qs_ctx("OK", "editor"), this);
	connect(pb, SIGNAL(clicked()), this, SLOT(okClicked()));
	pb->setMinimumWidth(80);
	g->addWidget(pb, 4, 4, 1, 2);

	pb = new QPushButton(__tr2qs_ctx("Cancel", "editor"), this);
	connect(pb, SIGNAL(clicked()), this, SLOT(reject()));
	pb->setMinimumWidth(80);
	g->addWidget(pb, 4, 3);

	m_pAdvancedButton = new QPushButton(__tr2qs_ctx("Advanced...", "editor"), this);
	connect(m_pAdvancedButton, SIGNAL(clicked()), this, SLOT(advancedClicked()));
	m_pAdvancedButton->setMinimumWidth(110);
	g->addWidget(m_pAdvancedButton, 4, 0, 1, 2);

	g->setRowStretch(0, 1);
	g->setColumnStretch(2, 1);
}

CustomToolBarPropertiesDialog::~CustomToolBarPropertiesDialog()
    = default;

void CustomToolBarPropertiesDialog::iconSelected(const QString & szIconId)
{
	QPixmap * pix = g_pIconManager->getImage(szIconId);

	if(pix)
	{
		m_pIconButton->setIcon(QIcon(*pix));
		m_szIconId = szIconId;
		m_pIconEdit->setText(szIconId);
	}
	else
	{
		m_pIconButton->setText(__tr2qs("&Browse..."));
		m_szIconId = "";
		m_pIconEdit->setText("");
	}
}

void CustomToolBarPropertiesDialog::iconButtonClicked()
{
	KviImageDialog * dlg = new KviImageDialog(this, __tr2qs_ctx("Choose a Toolbar Icon - KVIrc", "editor"));
	if(dlg->exec() != QDialog::Accepted)
	{
		delete dlg;
		return;
	}
	QString s = dlg->selectedImage();
	delete dlg;
	iconSelected(s);
}

void CustomToolBarPropertiesDialog::labelTextChanged(const QString & s)
{
	if(m_szOriginalId.isEmpty())
	{
		QString szId = KviCustomToolBarManager::instance()->idForNewToolBar(s);
		m_pIdEdit->setText(szId);
	}
}

void CustomToolBarPropertiesDialog::okClicked()
{
	if(m_szLabel.isEmpty())
	{
		QMessageBox::information(this, __tr2qs_ctx("Invalid Toolbar Label - KVIrc", "editor"), __tr2qs_ctx("The toolbar label can't be empty!", "editor"));
		return;
	}

	if(m_szId.isEmpty())
	{
		m_szId = KviCustomToolBarManager::instance()->idForNewToolBar(m_szLabel);
	}

	if(KviCustomToolBarManager::instance()->find(m_szId))
	{
		if(m_szId != m_szOriginalId)
		{
			QMessageBox pMsgBox;
			pMsgBox.setWindowTitle(__tr2qs_ctx("Duplicate Toolbar ID - KVIrc", "editor"));
			pMsgBox.setText(__tr2qs_ctx("The specified toolbar ID already exists.<br>"
						                "Would you like KVIrc to assign it automatically (so it doesn't "
						                "collide with any other toolbar) or you prefer to do it manually?", "editor"));
			pMsgBox.setIcon(QMessageBox::Question);
			QAbstractButton * pYesButton = pMsgBox.addButton(__tr2qs_ctx("Manually", "editor"), QMessageBox::YesRole);
			QAbstractButton * pNoButton = pMsgBox.addButton(__tr2qs_ctx("Automatically", "editor"), QMessageBox::NoRole);
			pMsgBox.exec();
			if(pMsgBox.clickedButton() == pYesButton)
			{
				return;
			} else if(pMsgBox.clickedButton() == pNoButton || pMsgBox.clickedButton() == nullptr) {
				// nothing
			}
			m_szId = KviCustomToolBarManager::instance()->idForNewToolBar(m_szLabel);
		}
	}

	m_szId = m_pIdEdit->text();
	m_szLabel = m_pLabelEdit->text();
	accept();
}

void CustomToolBarPropertiesDialog::advancedClicked()
{
	if(m_pAdvanced->isVisible())
	{
		m_pAdvanced->hide();
		m_pAdvancedButton->setText(__tr2qs_ctx("Advanced...", "editor"));
	}
	else
	{
		m_pAdvanced->show();
		m_pAdvancedButton->setText(__tr2qs_ctx("Hide Advanced", "editor"));
	}
}

CustomizeToolBarsDialog::CustomizeToolBarsDialog(QWidget * p)
    : QWidget(p)
{
	setObjectName("Toolbar_editor");
	setWindowTitle(__tr2qs_ctx("Customize Toolbars - KVIrc", "editor"));
	setWindowIcon(*(g_pIconManager->getSmallIcon(KviIconManager::ToolBarEditor)));

	m_pInstance = this;

	QGridLayout * g = new QGridLayout(this);
	m_pDrawer = new KviActionDrawer(this);
	g->addWidget(m_pDrawer, 0, 0, 7, 1);

	QPushButton * b = new QPushButton(__tr2qs_ctx("New Toolbar", "editor"), this);
	connect(b, SIGNAL(clicked()), this, SLOT(newToolBar()));
	g->addWidget(b, 0, 1);

	m_pDeleteToolBarButton = new QPushButton(__tr2qs_ctx("Delete Toolbar", "editor"), this);
	connect(m_pDeleteToolBarButton, SIGNAL(clicked()), this, SLOT(deleteToolBar()));
	g->addWidget(m_pDeleteToolBarButton, 1, 1);

	m_pRenameToolBarButton = new QPushButton(__tr2qs_ctx("Edit Toolbar", "editor"), this);
	connect(m_pRenameToolBarButton, SIGNAL(clicked()), this, SLOT(renameToolBar()));
	g->addWidget(m_pRenameToolBarButton, 2, 1);

	QFrame * f = new QFrame(this);
	f->setFrameStyle(QFrame::HLine | QFrame::Sunken);
	g->addWidget(f, 3, 1);

	m_pExportToolBarButton = new QPushButton(__tr2qs_ctx("Export Toolbar", "editor"), this);
	connect(m_pExportToolBarButton, SIGNAL(clicked()), this, SLOT(exportToolBar()));
	g->addWidget(m_pExportToolBarButton, 4, 1);

	m_pImportToolBarButton = new QPushButton(__tr2qs_ctx("Import Toolbar", "editor"), this);
	connect(m_pImportToolBarButton, SIGNAL(clicked()), this, SLOT(importToolBar()));
	g->addWidget(m_pImportToolBarButton, 5, 1);

	TrashcanLabel * t = new TrashcanLabel(this);
	g->addWidget(t, 7, 1);

	b = new QPushButton(__tr2qs_ctx("Close","editor"),this);
	connect(b,SIGNAL(clicked()), this, SLOT(closeClicked()));
	g->addWidget(b, 8, 1);

	g->setRowStretch(6, 1);
	g->setColumnStretch(0, 1);

	m_pDrawer->fill();

	connect(KviActionManager::instance(), SIGNAL(currentToolBarChanged()), this, SLOT(currentToolBarChanged()));
	KviActionManager::instance()->customizeToolBarsDialogCreated();

	currentToolBarChanged();

	if(g_rectToolBarEditorDialogGeometry.y() < 5)
	{
		g_rectToolBarEditorDialogGeometry.setY(5);
	}

	resize(g_rectToolBarEditorDialogGeometry.width(),
	    g_rectToolBarEditorDialogGeometry.height());
	move(g_rectToolBarEditorDialogGeometry.x(),
	    g_rectToolBarEditorDialogGeometry.y());

	new QShortcut(Qt::Key_Escape, this, SLOT(closeClicked()));
}

CustomizeToolBarsDialog::~CustomizeToolBarsDialog()
{
	g_rectToolBarEditorDialogGeometry = QRect(pos().x(), pos().y(), size().width(), size().height());

	KviActionManager::instance()->customizeToolBarsDialogDestroyed();
	m_pInstance = nullptr;
}

void CustomizeToolBarsDialog::currentToolBarChanged()
{
	m_pDeleteToolBarButton->setEnabled(KviActionManager::instance()->currentToolBar());
	m_pRenameToolBarButton->setEnabled(KviActionManager::instance()->currentToolBar());
}

void CustomizeToolBarsDialog::showEvent(QShowEvent * e)
{
	QRect rect = g_pMainWindow->screen()->availableGeometry();
	move(rect.x() + ((rect.width() - width()) / 2), rect.y() + ((rect.height() - height()) / 2));

	QWidget::showEvent(e);
}

void CustomizeToolBarsDialog::deleteToolBar()
{
	KviCustomToolBar * t = KviActionManager::currentToolBar();
	if(!t)
		return;
	if(QMessageBox::question(this,
	       __tr2qs_ctx("Confirm Toolbar Deletion - KVIrc", "editor"),
	       __tr2qs_ctx("Do you really want to delete toolbar \"%1\"?", "editor").arg(t->windowTitle()),
	       QMessageBox::Yes | QMessageBox::No,
	       QMessageBox::No)
	    != QMessageBox::Yes)
		return;
	KviCustomToolBarManager::instance()->destroyDescriptor(t->descriptor()->id());
}

void CustomizeToolBarsDialog::exportToolBar()
{
	KviCustomToolBar * t = KviActionManager::currentToolBar();
	if(!t)
		return;

	QString szName = QDir::homePath();
	if(!szName.endsWith(QString(KVI_PATH_SEPARATOR)))
		szName += KVI_PATH_SEPARATOR;
	szName += t->descriptor()->id();
	szName += ".kvs";

	QString szFile;

	if(!KviFileDialog::askForSaveFileName(szFile, __tr2qs_ctx("Enter a Filename - KVIrc", "editor"), szName, KVI_FILTER_SCRIPT, true, true, true, this))
		return;

	QString szCode;

	QMessageBox::StandardButton ret = QMessageBox::question(this,
	    __tr2qs_ctx("Confirm Toolbar Export - KVIrc", "editor"),
	    __tr2qs_ctx("Do you want the associated actions to be exported with the toolbar?", "editor"),
	    QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);

	if(ret == QMessageBox::Cancel)
		return;

	if(ret == QMessageBox::Yes)
	{
		KviPointerList<QString> * a = t->descriptor()->actions();
		if(a)
		{
			for(QString * s = a->first(); s; s = a->next())
			{
				KviAction * act = KviActionManager::instance()->getAction(*s);
				if(act)
				{
					if(act->isKviUserActionNeverOverrideThis())
					{
						((KviKvsUserAction *)act)->exportToKvs(szCode);
						szCode += "\n\n";
					}
				}
			}
		}
	}

	szCode += "toolbar.create ";
	szCode += t->descriptor()->id();
	szCode += " ";
	szCode += t->descriptor()->labelCode();
	szCode += " ";
	szCode += t->descriptor()->iconId();
	szCode += "\n";

	KviPointerList<QString> * aa = t->descriptor()->actions();
	if(aa)
	{
		for(QString * ss = aa->first(); ss; ss = aa->next())
		{
			szCode += "toolbar.additem ";
			szCode += t->descriptor()->id();
			szCode += " ";
			szCode += *ss;
			szCode += "\n";
		}
	}

	szCode += "toolbar.show ";
	szCode += t->descriptor()->id();
	szCode += "\n";

	if(!KviFileUtils::writeFile(szFile, szCode))
	{
		QMessageBox::warning(this, __tr2qs_ctx("Write to Toolbar File Failed - KVIrc", "editor"), __tr2qs_ctx("Unable to write to the toolbar file.", "editor"));
	}
}

void CustomizeToolBarsDialog::importToolBar()
{
	g_pMainWindow->executeInternalCommand(KVI_INTERNALCOMMAND_EXECUTE_SCRIPT_FROM_DISK);
}

void CustomizeToolBarsDialog::renameToolBar()
{
	KviCustomToolBar * t = KviActionManager::currentToolBar();
	if(!t)
		return;

	CustomToolBarPropertiesDialog * dlg = new CustomToolBarPropertiesDialog(this,
	    __tr2qs_ctx("Please specify the properties for the toolbar \"%1\"", "editor").arg(t->windowTitle()),
	    t->descriptor()->id(),
	    t->descriptor()->labelCode(),
	    t->descriptor()->iconId());

	dlg->show();
	if(dlg->exec() != QDialog::Accepted)
	{
		delete dlg;
		return;
	}

	QString id = dlg->id();
	QString label = dlg->label();
	QString icon = dlg->iconId();
	delete dlg;

	if((id == t->descriptor()->id()) && (label == t->descriptor()->labelCode()) && (icon == t->descriptor()->iconId()))
		return;

	KviCustomToolBarManager::instance()->renameDescriptor(t->descriptor()->id(), id, label);
	t->descriptor()->setIconId(icon);
}

void CustomizeToolBarsDialog::newToolBar()
{
	CustomToolBarPropertiesDialog * dlg = new CustomToolBarPropertiesDialog(this,
	    __tr2qs_ctx("Please specify the properties for the new toolbar", "editor"),
	    KviCustomToolBarManager::instance()->idForNewToolBar(__tr2qs_ctx("My Toolbar", "editor")),
	    __tr2qs_ctx("My Toolbar", "editor"));

	dlg->show();
	if(dlg->exec() != QDialog::Accepted)
	{
		delete dlg;
		return;
	}

	QString id = dlg->id();
	QString label = dlg->label();
	QString icon = dlg->iconId();
	delete dlg;

	KviCustomToolBarDescriptor * d = KviCustomToolBarManager::instance()->create(id, label);
	d->setIconId(icon);
	KviCustomToolBar * t = d->createToolBar();
	KviActionManager::instance()->setCurrentToolBar(t);
}

void CustomizeToolBarsDialog::closeClicked()
{
	delete this;
}

void CustomizeToolBarsDialog::cleanup()
{
	if(!m_pInstance)
		return;
	delete m_pInstance;
	m_pInstance = nullptr;
}

void CustomizeToolBarsDialog::display(bool bTopLevel)
{
	if(m_pInstance)
	{
		if(bTopLevel)
		{
			if(m_pInstance->parent())
			{
				m_pInstance->setParent(nullptr);
			}
		}
		else
		{
			if(m_pInstance->parent() != g_pMainWindow->splitter())
			{
				m_pInstance->setParent(g_pMainWindow->splitter());
			}
		}
	}
	else
	{
		if(bTopLevel)
		{
			m_pInstance = new CustomizeToolBarsDialog(nullptr);
		}
		else
		{
			m_pInstance = new CustomizeToolBarsDialog(g_pMainWindow->splitter());
		}
	}
	m_pInstance->show();
	m_pInstance->raise();
	m_pInstance->setFocus();
}

void CustomizeToolBarsDialog::closeEvent(QCloseEvent * e)
{
	e->ignore();
	delete this;
}

void CustomizeToolBarsDialog::reject()
{
	cleanup();
}
