#include "manualcookwindow.h"
#include "ui_manualcookwindow.h"

#include <QSignalMapper>
#include <QTimer>
#include <QtDebug>

ManualCookWindow::ManualCookWindow(QWidget *parent, Oven *oven, UdpHandler *udp) :
    QMainWindow(parent),
    ui(new Ui::ManualCookWindow), oven(oven), udp(udp)
{
    ui->setupUi(this);

    connect(oven, SIGNAL(changed(Oven*)), this, SLOT(onOvenUpdated(Oven*)));

    connect(ui->steamButton, SIGNAL(clicked()), this, SIGNAL(modeButtonClicked()));
    connect(ui->combiButton, SIGNAL(clicked()), this, SIGNAL(modeButtonClicked()));
    connect(ui->dryheatButton, SIGNAL(clicked()), this, SIGNAL(modeButtonClicked()));

    QSignalMapper *sm = new QSignalMapper(this);
    sm->setMapping(ui->steamButton, (int) Oven::SteamMode);
    sm->setMapping(ui->combiButton, (int) Oven::CombinationMode);
    sm->setMapping(ui->dryheatButton, (int) Oven::HeatMode);
    connect(ui->steamButton, SIGNAL(clicked()), sm, SLOT(map()));
    connect(ui->combiButton, SIGNAL(clicked()), sm, SLOT(map()));
    connect(ui->dryheatButton, SIGNAL(clicked()), sm, SLOT(map()));
    connect(sm, SIGNAL(mapped(int)), this, SLOT(onModeButtonClicked(int)));

    connect(ui->humiditySlider, SIGNAL(valueChanged(int)), oven, SLOT(setHumidity(int)));
    connect(ui->tempSlider, SIGNAL(valueChanged(int)), oven, SLOT(setTemp(int)));
    connect(ui->timeSlider, SIGNAL(valueChanged(int)), oven, SLOT(setTime(int)));
    connect(ui->interTempSlider, SIGNAL(valueChanged(int)), oven, SLOT(setInterTemp(int)));

    connect(ui->humiditySlider, SIGNAL(sliderMoved(int)), this, SLOT(updateLabels()));
    connect(ui->tempSlider, SIGNAL(sliderMoved(int)), this, SLOT(updateLabels()));
    connect(ui->timeSlider, SIGNAL(sliderMoved(int)), this, SLOT(updateLabels()));
    connect(ui->interTempSlider, SIGNAL(sliderMoved(int)), this, SLOT(updateLabels()));
    connect(ui->innerInterTempSlider, SIGNAL(sliderMoved(int)), this, SLOT(updateLabels()));
    connect(ui->innerInterTempSlider, SIGNAL(valueChanged(int)), this, SLOT(updateLabels()));

    QTimer *cookingTimerCheckTimer = new QTimer(this);
    cookingTimerCheckTimer->setInterval(100);
    connect(cookingTimerCheckTimer, SIGNAL(timeout()), this, SLOT(checkTime()));
    connect(this, SIGNAL(modeButtonClicked()), cookingTimerCheckTimer, SLOT(stop()));

    QTimer *cookingStartTimer = new QTimer(this);
    cookingStartTimer->setSingleShot(true);
    cookingStartTimer->setInterval(3000);
    connect(ui->timeSlider, SIGNAL(valueChanged(int)), cookingStartTimer, SLOT(start()));
    connect(ui->timeSlider, SIGNAL(valueChanged(int)), this, SLOT(updateLabels()));
    connect(this, SIGNAL(modeButtonClicked()), cookingStartTimer, SLOT(stop()));
    connect(cookingStartTimer, SIGNAL(timeout()), oven, SLOT(startCooking()));
    connect(cookingStartTimer, SIGNAL(timeout()), cookingTimerCheckTimer, SLOT(start()));

    QTimer *showCurHumTimer = new QTimer(this);
    QTimer *showCurTempTimer = new QTimer(this);
    showCurHumTimer->setInterval(2000);
    showCurTempTimer->setInterval(2000);

    connect(ui->humidityButton, SIGNAL(pressed()), showCurHumTimer, SLOT(start()));
    connect(ui->humidityButton, SIGNAL(released()), showCurHumTimer, SLOT(stop()));
    connect(showCurHumTimer, SIGNAL(timeout()), this, SLOT(showCurrentHumidity()));
    connect(ui->humidityButton, SIGNAL(released()), this, SLOT(hideCurrentHumidity()));

    connect(ui->tempButton, SIGNAL(pressed()), showCurTempTimer, SLOT(start()));
    connect(ui->tempButton, SIGNAL(released()), showCurTempTimer, SLOT(stop()));
    connect(showCurTempTimer, SIGNAL(timeout()), this, SLOT(showCurrentTemp()));
    connect(ui->tempButton, SIGNAL(released()), this, SLOT(hideCurrentTemp()));

    QSignalMapper *smStack = new QSignalMapper(this);
    smStack->setMapping(ui->goFrontStackButton, 0);
    smStack->setMapping(ui->goBackStackButton, 1);
    connect(ui->goFrontStackButton, SIGNAL(clicked()), smStack, SLOT(map()));
    connect(ui->goBackStackButton, SIGNAL(clicked()), smStack, SLOT(map()));
    connect(smStack, SIGNAL(mapped(int)), ui->buttonStack, SLOT(setCurrentIndex(int)));

    connect(ui->backButton, SIGNAL(clicked()), this, SLOT(hide()));
    connect(ui->backButton, SIGNAL(clicked()), oven, SLOT(stop()));
    connect(ui->backButton, SIGNAL(clicked()), cookingTimerCheckTimer, SLOT(stop()));
    connect(ui->backButton, SIGNAL(clicked()), cookingStartTimer, SLOT(stop()));
    connect(ui->backButton, SIGNAL(clicked()), showCurHumTimer, SLOT(stop()));
    connect(ui->backButton, SIGNAL(clicked()), showCurTempTimer, SLOT(stop()));

    connect(this, SIGNAL(cookStopRequested()), cookingStartTimer, SLOT(stop()));

    ui->bodyStack->setCurrentIndex(0);
}

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

void ManualCookWindow::checkTime()
{
    if (oven->cooking() && !ui->timeSlider->isSliderDown())
    {
        bool old = ui->timeSlider->blockSignals(true);
        ui->timeSlider->setSliderPosition(oven->time());
        ui->timeSlider->blockSignals(old);

        updateLabels();
    }
}

void ManualCookWindow::showCurrentHumidity()
{
    showCurrentHumidity_ = true;
    updateLabels();
}

void ManualCookWindow::hideCurrentHumidity()
{
    showCurrentHumidity_ = false;
    updateLabels();
}

void ManualCookWindow::showCurrentTemp()
{
    showCurrentTemp_ = true;
    updateLabels();
}

void ManualCookWindow::hideCurrentTemp()
{
    showCurrentTemp_ = false;
    updateLabels();
}

void ManualCookWindow::updateLabels()
{
    QString buf;

    int humidity;
    if (showCurrentHumidity_)
        humidity = oven->currentHumidity();
    else if (ui->humiditySlider->isSliderDown())
        humidity = ui->humiditySlider->sliderPosition();
    else
        humidity = oven->humidity();

    ui->humidityLabel->setText(buf.sprintf("%d%%", humidity));

    int temp;
    if (showCurrentTemp_)
        temp = oven->currentTemp();
    else if (ui->tempSlider->isSliderDown())
        temp = ui->tempSlider->sliderPosition();
    else
        temp = oven->temp();

    ui->tempLabel->setText(buf.sprintf("%d℃", temp));

    int time;
    if (ui->timeSlider->isSliderDown())
        time = ui->timeSlider->sliderPosition();
    else
        time = oven->time();

    if (time >= 3600)
        ui->timeLabel->setText(buf.sprintf("%d시간 %02d분", time / 3600, (time % 3600) / 60));
    else if (time >= 60)
        ui->timeLabel->setText(buf.sprintf("%d분 %02d초", time / 60, time % 60));
    else
        ui->timeLabel->setText(buf.sprintf("%d초", time));

    if (oven->interTempEnabled())
    {
        int interTemp;
        if (ui->interTempSlider->isSliderDown())
            interTemp = ui->interTempSlider->sliderPosition();
        else
            interTemp = oven->interTemp();

        ui->interTempLabel->setText(buf.sprintf("%d℃", interTemp));
    }
    else
        ui->interTempLabel->setText("℃");

    int innerInterTemp = ui->innerInterTempSlider->sliderPosition();
//    if (ui->innerInterTempSlider->isSliderDown())
//        innerInterTemp = ui->innerInterTempSlider->sliderPosition();
//    else
//        innerInterTemp = oven->interTemp();

    ui->innerInterTempLabel->setText(buf.sprintf("%d℃", innerInterTemp));

    ui->curHumidityLabel->setText(buf.sprintf("%d", oven->currentHumidity()));
    ui->targetHumidityLabel->setText(buf.sprintf("%d", oven->humidity()));
    ui->curTempLabel->setText(buf.sprintf("%d", oven->currentTemp()));
    ui->curInterTempLabel->setText(buf.sprintf("%d", oven->currentInterTemp()));
}

void ManualCookWindow::onModeButtonClicked(int mode)
{
    oven->stop();
    oven->setDefault((Oven::Mode) mode);
    ui->bodyStack->setCurrentIndex(0);
}

void ManualCookWindow::onOvenUpdated(Oven *oven)
{
    ui->steamIndicator->hide();
    ui->combiIndicator->hide();
    ui->dryheatIndicator->hide();
    ui->steamLabel->setEnabled(false);
    ui->combiLabel->setEnabled(false);
    ui->dryheatLabel->setEnabled(false);

    switch (oven->mode())
    {
    case Oven::HeatMode:
        ui->dryheatButton->setChecked(true);
        ui->dryheatIndicator->show();
        ui->dryheatLabel->setEnabled(true);
        break;
    case Oven::SteamMode:
        ui->steamButton->setChecked(true);
        ui->steamIndicator->show();
        ui->steamLabel->setEnabled(true);
        break;
    case Oven::CombinationMode:
        ui->combiButton->setChecked(true);
        ui->combiIndicator->show();
        ui->combiLabel->setEnabled(true);
        break;
    default:
        break;
    }

    bool old;
    old = ui->humiditySlider->blockSignals(true);
    ui->humiditySlider->setValue(oven->humidity());
    ui->humiditySlider->blockSignals(old);

    old = ui->tempSlider->blockSignals(true);
    ui->tempSlider->setRange(oven->minTemp(), oven->maxTemp());
    ui->tempSlider->setValue(oven->temp());
    ui->tempSlider->blockSignals(old);

    if (!ui->timeSlider->isSliderDown())
    {
        old = ui->timeSlider->blockSignals(true);
        ui->timeSlider->setValue(oven->time());
        ui->timeSlider->blockSignals(old);
    }

//    ui->interTempButton->setChecked(oven->interTempEnabled());
    if (oven->interTempEnabled())
        ui->interTempButton->setStyleSheet("\
QPushButton#interTempButton {\
    border-image: url(:/images/images/manual/011_icon_04_ov_01.png);\
}\
QPushButton#interTempButton:pressed {\
    border-image: url(:/images/images/manual/011_icon_04_ov.png);\
}");
    else
        ui->interTempButton->setStyleSheet("\
QPushButton#interTempButton {\
    border-image: url(:/images/images/manual/011_icon_04.png);\
}\
QPushButton#interTempButton:pressed {\
    border-image: url(:/images/images/manual/011_icon_04_ov.png);\
}");

    old = ui->interTempSlider->blockSignals(true);
    ui->interTempSlider->setEnabled(oven->interTempEnabled());
    ui->interTempSlider->setRange(oven->minInterTemp(), oven->maxInterTemp());
    ui->interTempSlider->setValue(oven->interTemp());
    ui->interTempSlider->blockSignals(old);

    old = ui->innerInterTempSlider->blockSignals(true);
    ui->innerInterTempSlider->setRange(oven->minInterTemp(), oven->maxInterTemp());
    ui->innerInterTempSlider->setValue(oven->interTemp());
    ui->innerInterTempSlider->blockSignals(old);

    if (oven->cooking())
        ui->runStopButton->setStyleSheet(
                    "border-image: url(:/images/images/manual/012_play_btn_ov_stop.png)");
    else
        ui->runStopButton->setStyleSheet(
                    "border-image: url(:/images/images/manual/012_play_btn.png)");

    if (oven->preheating())
        ui->preheatButton->setStyleSheet(
                    "border-image: url(:/images/images/manual/013_sys_icon_01_ov.png)");
    else
        ui->preheatButton->setStyleSheet(
                    "border-image: url(:/images/images/manual/013_sys_icon_01.png)");

    if (oven->damper())
        ui->damperButton->setStyleSheet(
                    "border-image: url(:/images/images/manual/013_sys_icon_02_ov.png)");
    else
        ui->damperButton->setStyleSheet(
                    "border-image: url(:/images/images/manual/013_sys_icon_02.png)");

    if (oven->humidification())
        ui->humidificationButton->setStyleSheet(
                    "border-image: url(:/images/images/manual/013_sys_icon_03_ov.png)");
    else
        ui->humidificationButton->setStyleSheet(
                    "border-image: url(:/images/images/manual/013_sys_icon_03.png)");

    if (oven->cooldown())
        ui->cooldownButton->setStyleSheet(
                    "border-image: url(:/images/images/manual/013_sys_icon_05_ov.png)");
    else
        ui->cooldownButton->setStyleSheet(
                    "border-image: url(:/images/images/manual/013_sys_icon_05.png)");

    switch (oven->fan())
    {
    case 1:
        ui->fanButton->setStyleSheet(
                    "border-image: url(:/images/images/manual/013_sys_icon_06.png)");
        break;
    case 2:
        ui->fanButton->setStyleSheet(
                    "border-image: url(:/images/images/manual/013_sys_icon_06_01.png)");
        break;
    case 3:
        ui->fanButton->setStyleSheet(
                    "border-image: url(:/images/images/manual/013_sys_icon_06_02.png)");
        break;
    case 4:
        ui->fanButton->setStyleSheet(
                    "border-image: url(:/images/images/manual/013_sys_icon_06_03.png)");
        break;
    case 5:
        ui->fanButton->setStyleSheet(
                    "border-image: url(:/images/images/manual/013_sys_icon_06_04.png)");
        break;
    default:
        ui->fanButton->setStyleSheet(
                    "border-image: url(:/images/images/manual/013_sys_icon_06.png)");
        break;
    }

    updateLabels();
}

void ManualCookWindow::on_runStopButton_clicked()
{
    if (oven->cooking())
    {
        oven->stopCooking();
        emit cookStopRequested();
    }
    else
        oven->startCooking();
}

void ManualCookWindow::on_fanButton_clicked()
{
    int fan = oven->fan() + 1;
    if (fan > oven->maxFan())
        fan = oven->minFan();

    oven->setFan(fan);
}

void ManualCookWindow::on_goOuterButton_clicked()
{
    ui->bodyStack->setCurrentIndex(0);
}

void ManualCookWindow::on_applyButton_clicked()
{
    ui->bodyStack->setCurrentIndex(0);

    oven->setInterTemp(ui->innerInterTempSlider->value());
    oven->setInterTempEnabled(true);
}

void ManualCookWindow::on_interTempButton_clicked()
{
    if (oven->interTempEnabled())
        oven->setInterTempEnabled(false);
    else
        ui->bodyStack->setCurrentIndex(1);
}

void ManualCookWindow::on_preheatButton_clicked()
{
    if (oven->preheating())
        oven->stopPreheating();
    else
        oven->startPreheating();
}

void ManualCookWindow::on_damperButton_clicked()
{
    if (oven->damper())
        oven->closeDamper();
    else
        oven->openDamper();
}

void ManualCookWindow::on_humidificationButton_clicked()
{
    if (oven->humidification())
        oven->stopHumidification();
    else
        oven->startHumidification();
}

void ManualCookWindow::on_repeatButton_clicked()
{

}

void ManualCookWindow::on_cooldownButton_clicked()
{
    if (oven->cooldown())
        oven->stopCooldown();
    else
        oven->startCooldown();
}

void ManualCookWindow::on_reserveButton_clicked()
{

}

void ManualCookWindow::on_favoritesButton_clicked()
{

}