#include "mqttitemsettingswidget.h"
#include "ui_mqttitemsettingswidget.h"

#include <QInputDialog>
#include <QDebug>

MqttItemSettingsWidget::MqttItemSettingsWidget(std::weak_ptr<MqttItem> item, QWidget *parent) :
	QWidget(parent),
	item_(item),
	ui(new Ui::MqttItemSettingsWidget)
{
	ui->setupUi(this);

	if(auto workingItem = item_.lock())
	{
		suppressUpdates_ = true;
		ui->lineEdit_topic->setText(workingItem->getTopic());
		ui->lineEdit_valueKey->setText(workingItem->getValueKey());
		ui->lineEdit_valueOn->setText(workingItem->getValueOn());
		ui->lineEdit_valueOff->setText(workingItem->getValueOff());
		ui->spinBox_min->setValue(workingItem->getValueMin());
		ui->spinBox_max->setValue(workingItem->getValueMax());
		ui->spinBox_step->setValue(workingItem->getValueStep());
		
		// Set value type combo
		switch(workingItem->getValueType())
		{
			case ITEM_VALUE_UINT:
				ui->comboBox_valueType->setCurrentIndex(1);
				break;
			case ITEM_VALUE_ENUM:
				ui->comboBox_valueType->setCurrentIndex(2);
				break;
			default:
				ui->comboBox_valueType->setCurrentIndex(0);
				break;
		}
		
		updateValueNamesFromItem();
		suppressUpdates_ = false;
		updateVisibility();
		
		// Connect expose loaded signal
		connect(workingItem.get(), &MqttItem::exposeLoaded, this, [this]() {
			if(auto item = item_.lock())
			{
				suppressUpdates_ = true;
				ui->label_status->setText("Detected!");
				
				// Update value type
				switch(item->getValueType())
				{
					case ITEM_VALUE_UINT:
						ui->comboBox_valueType->setCurrentIndex(1);
						break;
					case ITEM_VALUE_ENUM:
						ui->comboBox_valueType->setCurrentIndex(2);
						break;
					default:
						ui->comboBox_valueType->setCurrentIndex(0);
						break;
				}
				
				// Update limits
				ui->spinBox_min->setValue(item->getValueMin());
				ui->spinBox_max->setValue(item->getValueMax());
				ui->spinBox_step->setValue(item->getValueStep());
				
				// Update value on/off
				ui->lineEdit_valueOn->setText(item->getValueOn());
				ui->lineEdit_valueOff->setText(item->getValueOff());
				
				// Update value names
				updateValueNamesFromItem();
				suppressUpdates_ = false;
				updateVisibility();
			}
		});
	}

	// Connect signals
	connect(ui->lineEdit_topic, &QLineEdit::textChanged, this, &MqttItemSettingsWidget::setTopic);
	connect(ui->lineEdit_valueKey, &QLineEdit::textChanged, this, &MqttItemSettingsWidget::setValueKey);
	connect(ui->lineEdit_valueOn, &QLineEdit::textChanged, this, &MqttItemSettingsWidget::setValueOn);
	connect(ui->lineEdit_valueOff, &QLineEdit::textChanged, this, &MqttItemSettingsWidget::setValueOff);
	connect(ui->comboBox_valueType, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &MqttItemSettingsWidget::setValueType);
	connect(ui->spinBox_min, &QSpinBox::valueChanged, this, &MqttItemSettingsWidget::setValueMin);
	connect(ui->spinBox_max, &QSpinBox::valueChanged, this, &MqttItemSettingsWidget::setValueMax);
	connect(ui->spinBox_step, &QSpinBox::valueChanged, this, &MqttItemSettingsWidget::setValueStep);
	connect(ui->pushButton_autoDetect, &QPushButton::clicked, this, &MqttItemSettingsWidget::onAutoDetectClicked);
	connect(ui->pushButton_addValueName, &QPushButton::clicked, this, &MqttItemSettingsWidget::onAddValueName);
	connect(ui->pushButton_removeValueName, &QPushButton::clicked, this, &MqttItemSettingsWidget::onRemoveValueName);
	connect(ui->listWidget_valueNames, &QListWidget::itemChanged, this, &MqttItemSettingsWidget::onValueNamesChanged);
}

void MqttItemSettingsWidget::setTopic(const QString& topic)
{
	if(suppressUpdates_)
		return;
	if(auto workingItem = item_.lock())
	{
		workingItem->setTopic(topic);
	}
}

void MqttItemSettingsWidget::setValueKey(const QString& valueKey)
{
	if(suppressUpdates_)
		return;
	if(auto workingItem = item_.lock())
	{
		workingItem->setValueKey(valueKey);
	}
}

void MqttItemSettingsWidget::setValueOn(const QString& valueOn)
{
	if(suppressUpdates_)
		return;
	if(auto workingItem = item_.lock())
	{
		workingItem->setValueOn(valueOn);
	}
}

void MqttItemSettingsWidget::setValueOff(const QString& valueOff)
{
	if(suppressUpdates_)
		return;
	if(auto workingItem = item_.lock())
	{
		workingItem->setValueOff(valueOff);
	}
}

void MqttItemSettingsWidget::setValueType(int index)
{
	if(suppressUpdates_)
		return;
	if(auto workingItem = item_.lock())
	{
		item_value_type_t type;
		switch(index)
		{
			case 1: type = ITEM_VALUE_UINT; break;
			case 2: type = ITEM_VALUE_ENUM; break;
			default: type = ITEM_VALUE_BOOL; break;
		}
		workingItem->setValueType(type);
		updateVisibility();
	}
}

void MqttItemSettingsWidget::setValueMin(int min)
{
	if(suppressUpdates_)
		return;
	if(auto workingItem = item_.lock())
	{
		workingItem->setValueMin(min);
	}
}

void MqttItemSettingsWidget::setValueMax(int max)
{
	if(suppressUpdates_)
		return;
	if(auto workingItem = item_.lock())
	{
		workingItem->setValueMax(max);
	}
}

void MqttItemSettingsWidget::setValueStep(int step)
{
	if(suppressUpdates_)
		return;
	if(auto workingItem = item_.lock())
	{
		workingItem->setValueStep(step);
	}
}

void MqttItemSettingsWidget::onAutoDetectClicked()
{
	if(auto workingItem = item_.lock())
	{
		ui->label_status->setText("Detecting...");
		workingItem->triggerExposeLookup();
	}
}

void MqttItemSettingsWidget::onAddValueName()
{
	bool ok;
	QString name = QInputDialog::getText(this, "Add Value Name", "Enter value name:", QLineEdit::Normal, "", &ok);
	if(ok && !name.isEmpty())
	{
		ui->listWidget_valueNames->addItem(name);
		syncValueNamesToItem();
	}
}

void MqttItemSettingsWidget::onRemoveValueName()
{
	delete ui->listWidget_valueNames->currentItem();
	syncValueNamesToItem();
}

void MqttItemSettingsWidget::onValueNamesChanged()
{
	if(suppressUpdates_)
		return;
	syncValueNamesToItem();
}

void MqttItemSettingsWidget::syncValueNamesToItem()
{
	if(suppressUpdates_)
		return;
	if(auto workingItem = item_.lock())
	{
		std::vector<QString> names;
		for(int i = 0; i < ui->listWidget_valueNames->count(); ++i)
		{
			names.push_back(ui->listWidget_valueNames->item(i)->text());
		}
		workingItem->setValueNames(names);
	}
}

void MqttItemSettingsWidget::updateVisibility()
{
	int typeIndex = ui->comboBox_valueType->currentIndex();
	
	// Bool controls
	ui->label_valueOn->setVisible(typeIndex == 0);
	ui->lineEdit_valueOn->setVisible(typeIndex == 0);
	ui->label_valueOff->setVisible(typeIndex == 0);
	ui->lineEdit_valueOff->setVisible(typeIndex == 0);
	
	// UInt controls
	ui->label_min->setVisible(typeIndex == 1);
	ui->spinBox_min->setVisible(typeIndex == 1);
	ui->label_max->setVisible(typeIndex == 1);
	ui->spinBox_max->setVisible(typeIndex == 1);
	ui->label_step->setVisible(typeIndex == 1);
	ui->spinBox_step->setVisible(typeIndex == 1);
	
	// Enum controls
	ui->label_valueNames->setVisible(typeIndex == 2);
	ui->listWidget_valueNames->setVisible(typeIndex == 2);
	ui->pushButton_addValueName->setVisible(typeIndex == 2);
	ui->pushButton_removeValueName->setVisible(typeIndex == 2);
}

void MqttItemSettingsWidget::updateValueNamesFromItem()
{
	if(auto workingItem = item_.lock())
	{
		ui->listWidget_valueNames->clear();
		for(const QString& name : workingItem->getValueNames())
		{
			ui->listWidget_valueNames->addItem(name);
		}
	}
}

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