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

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

#include "preheatpopup.h"
#include "cooldownpopup.h"

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

    ui->clockContainer->setParent(ui->upperStack);
    ui->closeDoorWidget->setParent(ui->upperStack);
    ui->outerStack->setParent(ui->bodyStack);
    ui->innerStack->setParent(ui->bodyStack);
    setAttribute(Qt::WA_DeleteOnClose);

    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()));

    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);

    ui->openDoorAnimation->load(":/images/animation/door_big_09.png");
    ui->openDoorAnimation->load(":/images/animation/door_big_08.png");
    ui->openDoorAnimation->load(":/images/animation/door_big_07.png");
    ui->openDoorAnimation->load(":/images/animation/door_big_06.png");
    ui->openDoorAnimation->load(":/images/animation/door_big_05.png");
    ui->openDoorAnimation->load(":/images/animation/door_big_04.png");
    ui->openDoorAnimation->load(":/images/animation/door_big_03.png");
    ui->openDoorAnimation->load(":/images/animation/door_big_02.png");
    ui->openDoorAnimation->load(":/images/animation/door_big_01.png");
    ui->openDoorAnimation->start(300);
}

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<span style=\"font-size:11pt;\">℃</span>", temp));

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

    if (time >= 3600)
        ui->timeLabel->setText(buf.sprintf("%d<span style=\"font-size:11pt;\">시간</span> %02d<span style=\"font-size:11pt;\">분</span>", time / 3600, (time % 3600) / 60));
    else if (time >= 60)
        ui->timeLabel->setText(buf.sprintf("%d<span style=\"font-size:11pt;\">분</span> %02d<span style=\"font-size:11pt;\">초</span>", time / 60, time % 60));
    else
        ui->timeLabel->setText(buf.sprintf("%d<span style=\"font-size:11pt;\">초</span>", time));

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

        ui->interTempLabel->setText(buf.sprintf("%d<span style=\"font-size:11pt;\">℃</span>", interTemp));
    }
    else
        ui->interTempLabel->setText("<span style=\"font-size:11pt;\">℃</span>");

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

    ui->innerInterTempLabel->setText(buf.sprintf("%d<span style=\"font-size:11pt;\">℃</span>", 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)
{
    switch (oven->mode())
    {
    case Oven::HeatMode:
        ui->dryheatButton->setChecked(true);
        break;
    case Oven::SteamMode:
        ui->steamButton->setChecked(true);
        break;
    case Oven::CombinationMode:
        ui->combiButton->setChecked(true);
        break;
    default:
        break;
    }

    bool old;
    old = ui->humiditySlider->blockSignals(true);
    ui->humiditySlider->setValue(oven->humidity());
    ui->humiditySlider->setEnabled(oven->mode() == Oven::CombinationMode);
    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 {\
    image: url(:/images/slider_icon/core_temp_enabled.png);\
}\
QPushButton:pressed {\
    image: url(:/images/slider_icon/core_temp_ov.png);\
}");
    else
        ui->interTempButton->setStyleSheet("\
QPushButton {\
    image: url(:/images/slider_icon/core_temp.png);\
}\
QPushButton:pressed {\
    image: url(:/images/slider_icon/core_temp_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/manual_button/stop.png)");
    else
        ui->runStopButton->setStyleSheet(
                    "border-image: url(:/images/manual_button/run.png)");

    if (oven->damper())
        ui->damperButton->setStyleSheet(
                    "background-image: url(:/images/manual_button/damper_open.png)");
    else
        ui->damperButton->setStyleSheet(
                    "background-image: url(:/images/manual_button/damper_close.png)");

    if (oven->humidification())
        ui->humidificationButton->setStyleSheet(
                    "background-image: url(:/images/manual_button/side_nozzle_open.png)");
    else
        ui->humidificationButton->setStyleSheet(
                    "background-image: url(:/images/manual_button/side_nozzle_close.png)");

    switch (oven->fan())
    {
    case 1:
        ui->fanButton->setStyleSheet(
                    "background-image: url(:/images/manual_button/fan_1.png)");
        break;
    case 2:
        ui->fanButton->setStyleSheet(
                    "background-image: url(:/images/manual_button/fan_2.png)");
        break;
    case 3:
        ui->fanButton->setStyleSheet(
                    "background-image: url(:/images/manual_button/fan_3.png)");
        break;
    case 4:
        ui->fanButton->setStyleSheet(
                    "background-image: url(:/images/manual_button/fan_4.png)");
        break;
    case 5:
        ui->fanButton->setStyleSheet(
                    "background-image: url(:/images/manual_button/fan_5.png)");
        break;
    default:
        ui->fanButton->setStyleSheet(
                    "background-image: url(:/images/manual_button/fan_1.png)");
        break;
    }

    if (oven->paused() && !oven->cooldown() && oven->door())
        ui->upperStack->setCurrentIndex(1);
    else
        ui->upperStack->setCurrentIndex(0);

    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()
{
    cookingStartTimer->stop();

    PreheatPopup *p = new PreheatPopup(this, oven);
    p->setWindowModality(Qt::WindowModal);
    p->showFullScreen();
}

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()
{
    cookingStartTimer->stop();

    CooldownPopup *p = new CooldownPopup(this, oven);
    p->setWindowModality(Qt::WindowModal);
    p->showFullScreen();
}

void ManualCookWindow::on_reserveButton_clicked()
{

}

void ManualCookWindow::on_favoritesButton_clicked()
{

}