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

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

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

#include <QTime>

ManualCookWindow::ManualCookWindow(QWidget *parent, Define::Mode mode) :
    QMainWindow(parent),
    ui(new Ui::ManualCookWindow)
{
    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);

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

    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->timeSlider, SIGNAL(valueChanged(int)), &startCookingTimer, SLOT(start()));
    connect(ui->timeSlider, SIGNAL(valueChanged(int)), this, SLOT(updateLabels()));
    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()));

    checkTimeTimer.setInterval(100);
    connect(&checkTimeTimer, SIGNAL(timeout()), SLOT(checkTime()));

    startCookingTimer.setSingleShot(true);
    startCookingTimer.setInterval(3000);
    connect(&startCookingTimer, SIGNAL(timeout()), SLOT(start()));

    showCurrentHumidityTimer.setSingleShot(true);
    showCurrentHumidityTimer.setInterval(3000);
    connect(&showCurrentHumidityTimer, SIGNAL(timeout()), SLOT(showCurrentHumidity()));

    showCurrentTempTimer.setSingleShot(true);
    showCurrentTempTimer.setInterval(3000);
    connect(&showCurrentTempTimer, SIGNAL(timeout()), SLOT(showCurrentTemp()));

    ui->bodyStack->setCurrentIndex(0);

    QTimer *setupAnimationTimer = new QTimer(this);
    setupAnimationTimer->setSingleShot(true);
    connect(setupAnimationTimer, SIGNAL(timeout()), SLOT(setupAnimation()));

    oven->setDefault(mode);

    setupAnimationTimer->start(0);
}

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

void ManualCookWindow::setupAnimation()
{
    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);
}

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::onOvenUpdated(Oven *oven)
{
    switch (oven->mode())
    {
    case Define::DryMode:
        ui->dryheatButton->setChecked(true);
        break;
    case Define::SteamMode:
        ui->steamButton->setChecked(true);
        break;
    case Define::CombiMode:
        ui->combiButton->setChecked(true);
        break;
    default:
        break;
    }

    bool old;
    old = ui->humiditySlider->blockSignals(true);
    ui->humiditySlider->setValue(oven->humidity());
    ui->humiditySlider->setEnabled(oven->mode() == Define::CombiMode);
    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::setOvenDefault(Define::Mode mode)
{
    stop();

    oven->setDefault(mode);
    ui->bodyStack->setCurrentIndex(0);
}

void ManualCookWindow::start()
{
    oven->startCooking();
    checkTimeTimer.start();
}

void ManualCookWindow::stop()
{
    oven->stop();
    startCookingTimer.stop();
    checkTimeTimer.stop();
}

void ManualCookWindow::on_steamButton_clicked()
{
    setOvenDefault(Define::SteamMode);
}

void ManualCookWindow::on_combiButton_clicked()
{
    setOvenDefault(Define::CombiMode);
}

void ManualCookWindow::on_dryheatButton_clicked()
{
    setOvenDefault(Define::DryMode);
}

void ManualCookWindow::on_humidityButton_pressed()
{
    showCurrentHumidityTimer.start();
}

void ManualCookWindow::on_humidityButton_released()
{
    if (showCurrentHumidityTimer.isActive())
        showCurrentHumidityTimer.stop();
    else
        hideCurrentHumidity();
}

void ManualCookWindow::on_tempButton_pressed()
{
    showCurrentTempTimer.start();
}

void ManualCookWindow::on_tempButton_released()
{
    if (showCurrentTempTimer.isActive())
        showCurrentTempTimer.stop();
    else
        hideCurrentTemp();
}

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

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_runStopButton_clicked()
{
    if (oven->cooking())
    {
        stop();
    }
    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_preheatButton_clicked()
{
    startCookingTimer.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()
{
    startCookingTimer.stop();

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

void ManualCookWindow::on_reserveButton_clicked()
{

}

void ManualCookWindow::on_favoritesButton_clicked()
{

}

void ManualCookWindow::on_goBackStackButton_clicked()
{
    ui->buttonStack->setCurrentIndex(1);
}

void ManualCookWindow::on_goFrontStackButton_clicked()
{
    ui->buttonStack->setCurrentIndex(0);
}

void ManualCookWindow::on_backButton_clicked()
{
    stop();
    close();
}