#include "itemsettingsdialog.h"
#include "ui_itemsettingsdialog.h"
#include "../items/itemstore.h"
#include "actorsettingsdialog.h"
#include "../actors/alarmtime.h"
#include "../actors/sensoractor.h"
#include "../actors/timeractor.h"
#include "../actors/regulator.h"
#include "../actors/scriptactor.h"
#include "../items/messageitem.h"
#include "../items/systemitem.h"
#include "itemsettingswidgets/messageitemsettingswidget.h"
#include "itemsettingswidgets/systemitemsettingswidget.h"
#include "itemsettingswidgets/relayitemsettingswidget.h"
#include "itemsettingswidgets/mqttitemsettingswidget.h"
#include "../items/mqttitem.h"

#include<memory>

ItemSettingsDialog::ItemSettingsDialog(std::shared_ptr<Item> item, bool noGroup, QWidget *parent) :
	QDialog(parent),
	item_(item),
	ui(new Ui::ItemSettingsDialog)
{
	ui->setupUi(this);

	setModal(false);

	if(noGroup)
		ui->comboBox_Group->setEnabled(false);

	ui->label_name->setText(item_->getName());
	ui->checkBox_Override->setChecked(item_->getOverride());
	
	// Setup group combobox with editable mode for creating new groups
	ui->comboBox_Group->setEditable(true);
	ui->comboBox_Group->addItem("All");
	ui->comboBox_Group->addItems(getExistingGroups());
	ui->comboBox_Group->setCurrentText(item_->getGroupName());

	if(std::shared_ptr<Relay> relay = std::dynamic_pointer_cast<Relay>(item_))
	{
		itemSpecificWidget_ = new RelayItemSettingsWidget(relay);
	}
	else if(std::shared_ptr<MessageItem> msgItem = std::dynamic_pointer_cast<MessageItem>(item_))
	{
		itemSpecificWidget_ = new MessageItemSettingsWidget(msgItem);
	}
	else if(std::shared_ptr<SystemItem> sysItem = std::dynamic_pointer_cast<SystemItem>(item_))
	{
		itemSpecificWidget_ = new SystemItemSettingsWidget(sysItem);
	}
	else if(std::shared_ptr<MqttItem> mqttItem = std::dynamic_pointer_cast<MqttItem>(item_))
	{
		itemSpecificWidget_ = new MqttItemSettingsWidget(mqttItem);
	}

	if(itemSpecificWidget_)
	{
		ui->verticalLayout_2->addWidget(itemSpecificWidget_);
	}

	connect(ui->pushButton_add, &QPushButton::clicked, this, &ItemSettingsDialog::addActor);
	connect(ui->pushButton_remove, &QPushButton::clicked, this, &ItemSettingsDialog::removeActor);
	connect(ui->pushButton_edit, &QPushButton::clicked, this, &ItemSettingsDialog::editActor);
	connect(ui->checkBox_Override, &QPushButton::clicked, this, &ItemSettingsDialog::changeOverride);
	connect(ui->comboBox_Group, &QComboBox::currentTextChanged, this, &ItemSettingsDialog::changeGroup);


	ui->tableWidget->setHorizontalHeaderItem(0, new QTableWidgetItem("Actor"));
	ui->tableWidget->setHorizontalHeaderItem(1, new QTableWidgetItem("Action"));
	ui->tableWidget->setHorizontalHeaderItem(2, new QTableWidgetItem("Enabled"));
	ui->tableWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
	ui->tableWidget->horizontalHeader()->resizeSection(1, 60);
	ui->tableWidget->horizontalHeader()->resizeSection(2, 75);
	loadActorList();
}

ItemSettingsDialog::~ItemSettingsDialog()
{
	if(itemSpecificWidget_)
		delete itemSpecificWidget_;
	delete ui;
}

void ItemSettingsDialog::changeGroup()
{
	QString newGroup = ui->comboBox_Group->currentText();
	if(newGroup != item_->getGroupName())
	{
		ItemUpdateRequest update = item_->createValueUpdateRequest(ITEM_UPDATE_USER);
		update.payload.setGroupName(newGroup);
		update.changes.groupName = true;
		item_->requestUpdate(update);
	}
}

void ItemSettingsDialog::changeOverride()
{
	ItemUpdateRequest update = item_->createValueUpdateRequest(ITEM_UPDATE_USER);
	update.payload.setOverride(ui->checkBox_Override->isChecked());
	update.changes.override = true;
	item_->requestUpdate(update);
}

void ItemSettingsDialog::loadActorList()
{
	//ui->listWidget->clear();
	ui->tableWidget->setRowCount(item_->getActors().size());

	for(unsigned i = 0; i < item_->getActors().size(); i++)
	{
		ui->tableWidget->setItem(i, 0, new QTableWidgetItem(item_->getActors()[i]->getName()));
		ui->tableWidget->setItem(i, 1, new QTableWidgetItem(item_->getActors()[i]->actionName()));
		ui->tableWidget->setItem(i, 2, new QTableWidgetItem(item_->getActors()[i]->isActive() ? "Y" : "N"));
	}
}

void ItemSettingsDialog::addActor()
{
	ActorSettingsDialog* dialog = nullptr;
	std::shared_ptr<Actor> actor = nullptr;

	if(ui->comboBox->currentText() == "Alarm")
	{
		std::shared_ptr<AlarmTime> alarm = std::shared_ptr<AlarmTime>(new AlarmTime);
		actor = alarm;
		dialog = new ActorSettingsDialog(alarm, this);
	}
	else if(ui->comboBox->currentText() == "Sensor")
	{
		std::shared_ptr<SensorActor> sensorActor = std::shared_ptr<SensorActor>(new SensorActor);
		actor = sensorActor;
		dialog = new ActorSettingsDialog(sensorActor, this);
	}
	else if(ui->comboBox->currentText() == "Timer" )
	{
		std::shared_ptr<TimerActor> timerActor = std::shared_ptr<TimerActor>(new TimerActor);
		actor = timerActor;
		dialog = new ActorSettingsDialog(timerActor, this);
	}
	else if(ui->comboBox->currentText() == "Regulator")
	{
		std::shared_ptr<Regulator> regulator = std::shared_ptr<Regulator>(new Regulator);
		actor = regulator;
		dialog = new ActorSettingsDialog(regulator, this);
	}

	else if(ui->comboBox->currentText() == "Polynomal")
	{
		std::shared_ptr<PolynomalActor> polynomalActor = std::shared_ptr<PolynomalActor>(new PolynomalActor);
		actor = polynomalActor;
		dialog = new ActorSettingsDialog(polynomalActor, this);
	}
	else if(ui->comboBox->currentText() == "Script")
	{
		std::shared_ptr<ScriptActor> scriptActor = std::shared_ptr<ScriptActor>(new ScriptActor);
		actor = scriptActor;
		dialog = new ActorSettingsDialog(scriptActor, this);
	}


	if(dialog != nullptr)
	{
		dialog->setParent(this);
		if(dialog->exec() == QDialog::Accepted)
		{
			item_->addActor(actor);
			loadActorList();
		}
		delete dialog;
	}

}

void ItemSettingsDialog::removeActor()
{
	if(item_->getActors().size() > static_cast<size_t>(ui->tableWidget->currentRow()))
	{
		item_->removeActor(item_->getActors().at(ui->tableWidget->currentRow()));
		loadActorList();
	}
}

void ItemSettingsDialog::editActor()
{
	if(item_->getActors().size() > static_cast<size_t>(ui->tableWidget->currentRow()))
	{
		std::shared_ptr<Actor> actor = item_->getActors()[ui->tableWidget->currentRow()];

		std::shared_ptr<AlarmTime> alarmTime = std::dynamic_pointer_cast<AlarmTime>(actor);
		std::shared_ptr<Regulator> regulator = std::dynamic_pointer_cast<Regulator>(actor);
		std::shared_ptr<SensorActor> sensorActor = std::dynamic_pointer_cast<SensorActor>(actor);
		std::shared_ptr<TimerActor> timerActor = std::dynamic_pointer_cast<TimerActor>(actor);
		std::shared_ptr<PolynomalActor> polynomalActor = std::dynamic_pointer_cast<PolynomalActor>(actor);

		ActorSettingsDialog* dialog;

		if(alarmTime)
			dialog = new ActorSettingsDialog(alarmTime, this);
		else if(regulator)
			dialog = new ActorSettingsDialog(regulator, this);
		else if(sensorActor)
			dialog = new ActorSettingsDialog(sensorActor, this);
		else if(timerActor)
			dialog = new ActorSettingsDialog(timerActor, this);
		else if(polynomalActor)
			dialog = new ActorSettingsDialog(polynomalActor, this);
		else
			dialog = new ActorSettingsDialog(actor, this);

		dialog->exec();

		for(int i = 0; i < ui->tableWidget->rowCount() && i < static_cast<int>(item_->getActors().size()); ++i)
		{
			ui->tableWidget->item(i, 0)->setText(item_->getActors()[i]->getName());
			ui->tableWidget->item(i, 1)->setText(item_->getActors()[i]->actionName());
			ui->tableWidget->item(i, 2)->setText(item_->getActors()[i]->isActive() ? "Y" : "N");
		}
		delete dialog;
	}
}

QStringList ItemSettingsDialog::getExistingGroups()
{
	QSet<QString> uniqueGroups;
	for(const auto& item : *globalItems.getItems())
	{
		if(!item->getGroupName().isEmpty() && item->getGroupName() != "All")
		{
			uniqueGroups.insert(item->getGroupName());
		}
	}
	return uniqueGroups.values();
}
