/*
 * options.cpp - plugin widget
 *
 * Copyright (C) 2013  Ivan Romanov <drizt@land.ru>
 *
 * 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 "options.h"

#include "ui_options.h"
#include "optionaccessinghost.h"

#include <QComboBox>
#include <QLineEdit>
#include <QDebug>

Options::Options(const QList<Rule> &rules, QWidget *parent)
	: QWidget(parent)
	, ui(new Ui::Options)
	, _optionHost(0)
	, _rules(rules)
	, _currentRule(-1)
{
	ui->setupUi(this);

    ui->btAddRule->setIcon(QIcon::fromTheme("list-add", QIcon(":/icons/list-add.png")));
    ui->btRemoveRule->setIcon(QIcon::fromTheme("list-remove", QIcon(":/icons/list-remove.png")));
    ui->btUpRule->setIcon(qApp->style()->standardIcon(QStyle::SP_ArrowUp));
    ui->btDownRule->setIcon(qApp->style()->standardIcon(QStyle::SP_ArrowDown));

    ui->btAddCondition->setIcon(QIcon::fromTheme("list-add", QIcon(":/icons/list-add.png")));
    ui->btRemoveCondition->setIcon(QIcon::fromTheme("list-remove", QIcon(":/icons/list-remove.png")));
    ui->btUpCondition->setIcon(qApp->style()->standardIcon(QStyle::SP_ArrowUp));
    ui->btDownCondition->setIcon(qApp->style()->standardIcon(QStyle::SP_ArrowDown));

	ui->wRulePane->setEnabled(false);

	updateRuleButtons();
	updateConditionButtons();

	foreach (const Rule &rule, _rules) {
		ui->lwRules->addItem(rule.name);
	}
}

Options::~Options()
{
	delete ui;
}

void Options::update()
{
}

void Options::saveSettings()
{
	if (_currentRule >= 0) {
		_rules[_currentRule].name = ui->lneRuleName->text();
		_rules[_currentRule].showMessage = ui->chkShowMessage->isChecked();
		
		for (int i = 0; i < ui->twConditions->rowCount(); ++i)
			saveCondition(_currentRule, i);
	}

	_optionHost->setPluginOption("rules.size", _rules.size());
	for (int i = 0; i < _rules.size(); ++i) {
		QString optionName = QString("rules.l%1.").arg(i);
		Rule rule = _rules.at(i);
		_optionHost->setPluginOption(optionName + "name", rule.name);
		_optionHost->setPluginOption(optionName + "show-message", rule.showMessage);
		_optionHost->setPluginOption(optionName + "conditions.size", rule.conditions.size());
		for (int j = 0; j < rule.conditions.size(); ++j) {
			Condition condition = rule.conditions.at(j);
			QString optionName1 = QString("%1conditions.l%2.").arg(optionName).arg(j);
			_optionHost->setPluginOption(optionName1 + "type", static_cast<int>(condition.type));
			_optionHost->setPluginOption(optionName1 + "comparison", static_cast<int>(condition.comparison));
			_optionHost->setPluginOption(optionName1 + "text", condition.text);
		}
	}
}

void Options::addRule()
{
	ui->lwRules->addItem("New rule");

	Rule rule;
	rule.name = "New rule";
	rule.showMessage = false;
	
	_rules << rule;
	ui->lwRules->setCurrentRow(ui->lwRules->count() - 1);
	addCondition();
}

void Options::removeRule()
{
	int rule = ui->lwRules->currentRow();
	ui->lwRules->setCurrentRow(-1);
	_rules.removeAt(rule);
	delete ui->lwRules->takeItem(rule);

	ui->lwRules->setCurrentRow(rule == _rules.size() ? -1 : rule);
}

void Options::upRule()
{
	int rule = ui->lwRules->currentRow();
	_rules.swap(rule, rule - 1);

	QListWidgetItem *item = ui->lwRules->takeItem(rule);
	ui->lwRules->insertItem(rule - 1, item);

	ui->lwRules->setCurrentRow(rule - 1);
}

void Options::downRule()
{
	int rule = ui->lwRules->currentRow();
	_rules.swap(rule, rule + 1);

	QListWidgetItem *item = ui->lwRules->takeItem(rule);
	ui->lwRules->insertItem(rule + 1, item);

	ui->lwRules->setCurrentRow(rule + 1);
}

void Options::updateRuleButtons()
{
	if (ui->lwRules->currentRow() < 0) {
		ui->btRemoveRule->setEnabled(false);
		ui->btUpRule->setEnabled(false);
		ui->btDownRule->setEnabled(false);
	}
	else {
		ui->btRemoveRule->setEnabled(true);
		if (ui->lwRules->currentRow() > 0)
			ui->btUpRule->setEnabled(true);
		else
			ui->btUpRule->setEnabled(false);
		
		if (ui->lwRules->currentRow() <  ui->lwRules->count() - 1)
			ui->btDownRule->setEnabled(true);
		else
			ui->btDownRule->setEnabled(false);
	}
}

void Options::addCondition()
{
	Condition condition;
	condition.type = From;
	condition.comparison = Equal;
	condition.text = "";

	_rules[ui->lwRules->currentRow()].conditions << condition;
	setRulePane(ui->lwRules->currentRow());
}

void Options::removeCondition()
{
	int rule = ui->lwRules->currentRow();
	int condition = ui->twConditions->currentRow();
	
	_rules[rule].conditions.removeAt(condition);
	ui->twConditions->removeRow(condition);

	updateConditionButtons();
}

void Options::upCondition()
{
	int rule = ui->lwRules->currentRow();
	int condition = ui->twConditions->currentRow();
	int conditionColumn = ui->twConditions->currentColumn();

	saveCondition(rule, condition - 1);
	saveCondition(rule, condition);

	_rules[rule].conditions.swap(condition, condition - 1);

	fillCondition(condition - 1);
	fillCondition(condition);

	ui->twConditions->setCurrentCell(condition - 1, conditionColumn);
}

void Options::downCondition()
{
	int rule = ui->lwRules->currentRow();
	int condition = ui->twConditions->currentRow();
	int conditionColumn = ui->twConditions->currentColumn();

	saveCondition(rule, condition);
	saveCondition(rule, condition + 1);

	_rules[rule].conditions.swap(condition, condition + 1);

	fillCondition(condition);
	fillCondition(condition + 1);

	ui->twConditions->setCurrentCell(condition + 1, conditionColumn);
}

void Options::updateConditionButtons()
{
	if (ui->twConditions->currentRow() < 0) {
		ui->btRemoveCondition->setEnabled(false);
		ui->btUpCondition->setEnabled(false);
		ui->btDownCondition->setEnabled(false);
	}
	else {
		ui->btRemoveCondition->setEnabled(true);
		if (ui->twConditions->currentRow() > 0)
			ui->btUpCondition->setEnabled(true);
		else
			ui->btUpCondition->setEnabled(false);
		
		if (ui->twConditions->currentRow() <  ui->twConditions->rowCount() - 1)
			ui->btDownCondition->setEnabled(true);
		else
			ui->btDownCondition->setEnabled(false);
	}
}

void Options::updateRuleName(const QString &name)
{
	ui->lwRules->currentItem()->setText(name);
	_rules[ui->lwRules->currentRow()].name = name;
}

void Options::setRulePane(int row)
{
	if (_currentRule >= 0) {
		_rules[_currentRule].name = ui->lneRuleName->text();
		_rules[_currentRule].showMessage = ui->chkShowMessage->isChecked();
		
		for (int i = 0; i < ui->twConditions->rowCount(); ++i)
			saveCondition(_currentRule, i);
	}

	qDebug() << "New current row" << row;

	_currentRule = row;
	clearConditionsTable();
	if (row >= 0 && row < _rules.size()) {
		ui->wRulePane->setEnabled(true);
		Rule rule = _rules[row];
		ui->lneRuleName->setText(rule.name);
		ui->chkShowMessage->setChecked(rule.showMessage);
		QList<Condition> conditions = rule.conditions;
		for (int i = 0; i < conditions.size(); ++i) {
			ui->twConditions->insertRow(i);
			QComboBox *comboBox = new QComboBox();
			comboBox->addItem("From jid");
			comboBox->addItem("To jid");
			comboBox->addItem("From full jid");
			comboBox->addItem("To full jid");
			comboBox->addItem("Message");
			comboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
			ui->twConditions->setCellWidget(i, 0, comboBox);
			connect(comboBox, SIGNAL(currentIndexChanged(int)), SLOT(hack()));

			comboBox = new QComboBox();
			comboBox->addItem("equal");
			comboBox->addItem("not equal");
			comboBox->addItem("contains");
			comboBox->addItem("not contains");
			comboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
			ui->twConditions->setCellWidget(i, 1, comboBox);
			connect(comboBox, SIGNAL(currentIndexChanged(int)), SLOT(hack()));

			QLineEdit *lineEdit = new QLineEdit();
			lineEdit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
			ui->twConditions->setCellWidget(i, 2, lineEdit);
			connect(lineEdit, SIGNAL(textEdited(QString)), SLOT(hack()));
			
			fillCondition(i);
		}

#if QT_VERSION > QT_VERSION_CHECK(5, 0, 0)
		ui->twConditions->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
#else
		ui->twConditions->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents);
#endif
	}
	else {
		ui->wRulePane->setEnabled(false);
		ui->lneRuleName->setText("");
		ui->chkShowMessage->setChecked(false);
	}
	updateRuleButtons();
	updateConditionButtons();
}

// Hack to enable Apply button
void Options::hack()
{
	ui->chkShowMessage->toggle();
	ui->chkShowMessage->toggle();
}

void Options::clearConditionsTable()
{
	while (ui->twConditions->rowCount())
		ui->twConditions->removeRow(0);
}

void Options::fillCondition(int row)
{
	int rule = ui->lwRules->currentRow();
	qobject_cast<QComboBox*>(ui->twConditions->cellWidget(row, 0))->setCurrentIndex(_rules.at(rule).conditions.at(row).type);
	qobject_cast<QComboBox*>(ui->twConditions->cellWidget(row, 1))->setCurrentIndex(_rules.at(rule).conditions.at(row).comparison);
	qobject_cast<QLineEdit*>(ui->twConditions->cellWidget(row, 2))->setText(_rules.at(rule).conditions.at(row).text);
}

void Options::saveCondition(int rule, int row)
{
	_rules[rule].conditions[row].type = static_cast<ConditionType>(qobject_cast<QComboBox*>(ui->twConditions->cellWidget(row, 0))->currentIndex());
	_rules[rule].conditions[row].comparison = static_cast<Comparison>(qobject_cast<QComboBox*>(ui->twConditions->cellWidget(row, 1))->currentIndex());
	_rules[rule].conditions[row].text = qobject_cast<QLineEdit*>(ui->twConditions->cellWidget(row, 2))->text();
}
