#include "allDevicesWidget.h"
#include "deviceItemWidget.h"
#include "combinedSlider.h"
#include "protocol.h"
#include "softProj\helpers.h"


void DeviceItemWidget::energyPrioritySliderValueChangedSlot(unsigned long long value) {
	energyPriorityChanged(value);
}

void DeviceItemWidget::maximumEnergySliderValueChangedSlot(unsigned long long value) {
	maximumEnergyChanged(value);
}

void DeviceItemWidget::energyPriorityChanged(unsigned long long) {
	recolorFromPriority();
}

void DeviceItemWidget::maximumEnergyChanged(unsigned long long value) {
	if (value == minimumMaximumEnergy_) {
		deactivateDevice();
	}
	else {
		activateDevice();
	}
}

void DeviceItemWidget::setMinEnergyRatio(unsigned long long value) {
	this->ui_.energyRatioSlider->setMinimum(value);
}

void DeviceItemWidget::setMaxEnergyRatio(unsigned long long value) {
	this->ui_.energyRatioSlider->setMaximum(value);
}

void DeviceItemWidget::setEnergyRatio(unsigned long long value) {
	this->ui_.energyRatioSlider->setValue(value);
}

void DeviceItemWidget::setMinEnergyPriority(unsigned long long value) {
	this->ui_.energyPrioritySlider->setMinimum(value);	
}

void DeviceItemWidget::setMaxEnergyPriority(unsigned long long value) {
	this->ui_.energyPrioritySlider->setMaximum(value);	
}

void DeviceItemWidget::setEnergyPriority(unsigned long long value) {
	this->ui_.energyPrioritySlider->setValue(value);	
}

DeviceItemWidget::DeviceItemWidget(const std::wstring & name, QWidget * parent, DeviceBackgroundsHolder * backgroundsHolder) : QWidget(parent) {
	ui_.setupUi(this);

	this->parent_ = parent;

	isActive_ = true;

	backgroundsHolder_ = backgroundsHolder;	

	ui_.energyRatioSlider->setName(L"Podíl");
	ui_.energyPrioritySlider->setName(L"Priorita");

	ui_.maximumEnergySlider->setName(L"Max. energie");
	ui_.maximumEnergySlider->setUnit(L"GW");

	setDeviceName(name);
	
	bool ok = true;
	
	ok = ok && (QObject::connect(
		ui_.energyPrioritySlider, SIGNAL(valueChangedSignal(unsigned long long)),
		this, SLOT(energyPrioritySliderValueChangedSlot(unsigned long long))
	));

	ok = ok && (QObject::connect(
		ui_.maximumEnergySlider, SIGNAL(valueChangedSignal(unsigned long long)),
		this, SLOT(maximumEnergySliderValueChangedSlot(unsigned long long))
	));

	/* Settings change */ 

	ok = ok && (QObject::connect(
		ui_.maximumEnergySlider, SIGNAL(valueChangedSignal(unsigned long long)),
		this, SLOT(settingsChangedSlot())
	));

	ok = ok && (QObject::connect(
		ui_.energyPrioritySlider, SIGNAL(valueChangedSignal(unsigned long long)),
		this, SLOT(settingsChangedSlot())
	));

	ok = ok && (QObject::connect(
		ui_.energyRatioSlider, SIGNAL(valueChangedSignal(unsigned long long)),
		this, SLOT(settingsChangedSlot())
	));

	ok = ok && (QObject::connect(
		ui_.turnOffOnLackCheckBox, SIGNAL(stateChanged(int)),
		this, SLOT(settingsChangedSlot())
	));

	assert(ok && "Signals not connected");

	ui_.energyRatioSlider->setFontColor(QColor::fromRgb(40, 40, 40));
	ui_.energyPrioritySlider->setFontColor(QColor::fromRgb(40, 40, 40));
	ui_.maximumEnergySlider->setFontColor(QColor::fromRgb(40, 40, 40));
}

void DeviceItemWidget::settingsChangedSlot() {
	emit settingsChangedSignal();
}

requestDeviceEnergyState DeviceItemWidget::getState() {
	requestDeviceEnergyState state;

	// Convert from GW to TW
	state.maxPowerDrain = getMaximumEnergy();

	state.priority = getEnergyPriority();
	state.ratio = getEnergyRatio();
	state.shutDownOnEnergyLack = getShutDownOnEnergyLack();

	return state;
}

void DeviceItemWidget::setState(const answerDeviceEnergyState & state, const answerDeviceEnergy & fullState) {
	// Minimum max power drain comes as real value, no need to multiply
	setMinMaximumEnergy(fullState.MIN_MAX_ENERGY);
	// Convert from TW to GW
	setMaxMaximumEnergy(state.maxMaxPowerDrain);
	// Convert from TW to GW
	setMaximumEnergy(state.maxPowerDrain);

	setMinEnergyPriority(fullState.MIN_ENERGY_PRIORITY);
	setMaxEnergyPriority(fullState.MAX_ENERGY_PRIORITY);
	setEnergyPriority(state.priority);

	setMinEnergyRatio(fullState.MIN_RATIO);
	setMaxEnergyRatio(fullState.MAX_RATIO);
	setEnergyRatio(state.ratio);

	setShutDownOnEnergyLack(state.shutDownOnEnergyLack);

	// Convert from TW to GW
	setEnergyConsumption((unsigned long long) (state.consumption * 1000));

	if (state.maxPowerDrain > 0) {
		activateDevice();
	}
	else {
		deactivateDevice();
	}
}

void ChargeFrame::paintEvent(QPaintEvent * e) {
	QPainter painter(this);

	painter.setRenderHint(QPainter::Antialiasing, true);
	painter.setPen(QPen(Qt::black, 12, Qt::DashDotLine, Qt::RoundCap));

	if (maximumValue_ > 0) {
		int valueWidth  = width() / maximumValue_ * currentValue_;
		painter.fillRect(2, 2, valueWidth - 4, height() - 4, QColor::fromRgb(50, 95, 140));
	}

	QFrame::paintEvent(e);
}

void DeviceItemWidget::recolorFromPriority() {
	ui_.deviceFrame->setAutoFillBackground(true);

	unsigned int priority = getEnergyPriority();
	
	QString backgroundStyle = backgroundsHolder_->getBackgroundFromPriority(priority, isActive_);
	QString foregroundStyle = backgroundsHolder_->getForegroundFromPriority(priority, isActive_);

	ui_.deviceFrame->setStyleSheet(backgroundStyle);
}

void DeviceItemWidget::activateDevice() {
	isActive_ = true;
	ui_.onOffLabel->setText("Zapnuto");
	ui_.onOffLabel->setStyleSheet("#onOffLabel { font-weight: bold; color: rgb(110, 155, 80); }");
	recolorFromPriority();
}

void DeviceItemWidget::deactivateDevice() {
	isActive_ = false;
	ui_.onOffLabel->setText("Vypnuto");
	ui_.onOffLabel->setStyleSheet("#onOffLabel { font-weight: bold; color: rgb(170, 45, 44); }");
	refreshBackgroundColor();
}

void DeviceItemWidget::refreshBackgroundColor() {
	recolorFromPriority();
}

void DeviceItemWidget::setDeviceName(const std::wstring & deviceName) {
	ui_.nameButton->setText(QString::fromUtf16(deviceName.c_str()));
}	


void DeviceItemWidget::setDeviceIcon(const std::string & deviceIconPath) {
	ui_.nameButton->setLayoutDirection(Qt::RightToLeft);
	setButtonIconFromResources(ui_.nameButton, deviceIconPath, 24);
}

bool DeviceItemWidget::getShutDownOnEnergyLack() {
	return ui_.turnOffOnLackCheckBox->checkState() == Qt::Checked;
}

void DeviceItemWidget::setShutDownOnEnergyLack(bool value) {
	if (value) {
		ui_.turnOffOnLackCheckBox->setCheckState(Qt::Checked);
	}
	else {
		ui_.turnOffOnLackCheckBox->setCheckState(Qt::Unchecked);
	}
}

void DeviceItemWidget::setEnergyConsumption(unsigned long long value) {
	QString stringValue = Settings::instance().formatNumber(value);

	if (value > 0) {
		ui_.consumptionLabel->setText("- " +  stringValue + " GW");
	}
	else {
		ui_.consumptionLabel->setText("+ " +  stringValue + " GW");
	}
}

unsigned long long DeviceItemWidget::getEnergyRatio() {
	return ui_.energyRatioSlider->getValue();
}

unsigned long long DeviceItemWidget::getEnergyPriority() {
	return ui_.energyPrioritySlider->getValue();
}

double DeviceItemWidget::getMaximumEnergy() {
	return ((double) (ui_.maximumEnergySlider->getValue())) / 1000;
}

void DeviceItemWidget::setMaximumEnergy(double value) {
	ui_.maximumEnergySlider->setValue((unsigned long long) (value * 1000));
}

void DeviceItemWidget::setMaxMaximumEnergy(double value) {
	ui_.maximumEnergySlider->setMaximum((unsigned long long) (value * 1000));
}

void DeviceItemWidget::setMinMaximumEnergy(double value) {
	minimumMaximumEnergy_ = value;
	ui_.maximumEnergySlider->setMinimum(value);
}

void DeviceBackgroundsHolder::setLimits(unsigned long long min, unsigned long long max) {
	minimumEnergyPriority_ = min;
	maximumEnergyPriority_ = max;

	activeBackgroundStyles_.clear();
	deactiveBackgroundStyles_.clear();
	foregroundStyles_.clear();

	if (max = 0) {
		return;
	}

	int redCoefficitent = (250 - 70) / maximumEnergyPriority_;
	int greenCoefficitent = (250 - 30) / maximumEnergyPriority_;
	int blueCoefficitent = (250 - 70) / maximumEnergyPriority_;

	for (int i = 0; i < maximumEnergyPriority_; ++i) {
		int backgroundPart = i * maximumEnergyPriority_ + 1;

		int foregroundPart;

		QString backgroundString = QString::number(backgroundPart);
		deactiveBackgroundStyles_.push_back("#deviceFrame { background-color: rgb(" 
			+ backgroundString + ", " + backgroundString + ", " + backgroundString + ", 250); }");
		
		if (i < maximumEnergyPriority_ / 2) {
			foregroundPart = 255;
		}
		else {
			foregroundPart = 0;
		}

		QString foregroundString = QString::number(foregroundPart);
		foregroundStyles_.push_back("color: rgb(" + foregroundString + ", " + foregroundString + ", " + foregroundString + ", 255);");

		activeBackgroundStyles_.push_back("#deviceFrame { background-color: rgb("
			+ QString::number(20 + (i * redCoefficitent)) + ", " + QString::number(60 + (i * greenCoefficitent)) + ", " + QString::number(20 + (i * blueCoefficitent)) + ", 250); }");
	}
}

QString & DeviceBackgroundsHolder::getBackgroundFromPriority(unsigned long long priority, bool isActive) {
	if (isActive) {
		unsigned long long index = priority - minimumEnergyPriority_;

		if (index < 0 || index  >= maximumEnergyPriority_) {
			return emptyStyle_;
		}

		return activeBackgroundStyles_[index];
	}
	else {
		unsigned long long index = priority - minimumEnergyPriority_;

		if (index < 0 || index  >= maximumEnergyPriority_) {
			return emptyStyle_;
		}

		return deactiveBackgroundStyles_[index];
	}
}

QString & DeviceBackgroundsHolder::getForegroundFromPriority(unsigned long long priority, bool isActive) {
	unsigned long long index = priority - minimumEnergyPriority_;

	if (index < 0 || index  >= maximumEnergyPriority_) {
		return emptyStyle_;
	}

	return foregroundStyles_[index];
}

DeviceBackgroundsHolder::DeviceBackgroundsHolder() {
	emptyStyle_ = "";
}