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

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

#include "soundplayer.h"
#include "preheatpopup.h"
#include "cooldownpopup.h"
#include "cookhistory.h"
#include "favoritenamepopup.h"
#include "confirmpopup.h"
#include "stringer.h"
#include "config.h"
#include "coretempsettingpopup.h"
#include "reservetimepopup.h"
#include "reservedtimepopup.h"
#include "mainwindow.h"
#include "configwindow.h"
#include "primewindow.h"
#include "washwindow.h"
#include "errorpopupdlg.h"

#include <QTime>

ManualCookWindow::ManualCookWindow(QWidget *parent, Define::Mode mode) :
    QMainWindow(parent),
    ui(new Ui::ManualCookWindow),
    repeat(false)
{
    ui->setupUi(this);

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

    oven = Oven::getInstance();

    ui->humiditySlider->setSubPixmap(":/images/slider/humidity.png");
    ui->humiditySlider->setRange(0, 100);
    ui->humiditySlider->bigTickInterval = 50;
    ui->humiditySlider->tickInterval = 10;

    ui->tempSlider->setSubPixmap(":/images/slider/temp.png");
    ui->tempSlider->bigTickInterval = 50;
    ui->tempSlider->tickInterval = 10;

    ui->timeSlider->setSubPixmap(":/images/slider/time.png");
    ui->timeSlider->setRange(0, 342);
    ui->timeSlider->bigTicks.append(0);
    ui->timeSlider->bigTicks.append(180);
    ui->timeSlider->bigTicks.append(270);
    ui->timeSlider->bigTicks.append(342);
    ui->timeSlider->ticks.append(60);
    ui->timeSlider->ticks.append(120);
    ui->timeSlider->ticks.append(180 + 30);
    ui->timeSlider->ticks.append(180 + 60);
    ui->timeSlider->ticks.append(270 + 4 * 6);
    ui->timeSlider->ticks.append(270 + 4 * 12);

    ui->interTempSlider->setSubPixmap(":/images/slider/core.png");

    QList<int> &bigTicks = ui->interTempSlider->bigTicks;
    bigTicks.append(oven->minInterTemp());
    bigTicks.append(oven->minInterTemp() + (oven->maxInterTemp() - oven->minInterTemp()) / 2);
    bigTicks.append(oven->maxInterTemp());

    QList<int> &ticks = ui->interTempSlider->ticks;
    for (int i = 1; i < 3; i++)
        ticks.append(bigTicks.at(0) + i * (bigTicks.at(1) - bigTicks.at(0)) / 3);
    for (int i = 1; i < 3; i++)
        ticks.append(bigTicks.at(1) + i * (bigTicks.at(2) - bigTicks.at(1)) / 3);


    lastViewHumidity = -1;
    lastViewTemp = -1;
    lastViewTime = -1;
    lastViewInterTemp = -1;
    lastViewInterTempEnabled = !oven->interTempEnabled();
    lastViewCooking = false;
    lastViewDamper = false;
    lastViewHumidification = false;
    lastViewFan = -1;
    lastCheckedCooking = false;

    Config *config = Config::getInstance();
    config_item item = config->getConfigValue(Define::config_cooking_door_monitoring);

    monitorLevel = item.d8.d8_0;
    if (monitorLevel > 0 && monitorLevel < 4)
    {
        monitor1.setSingleShot(true);
        monitor2.setSingleShot(true);
        monitor3.setSingleShot(true);
        monitor1.setInterval(item.d8.d8_1 * 1000);
        monitor2.setInterval(item.d8.d8_2 * 1000);
        monitor3.setInterval(item.d8.d8_3 * 1000);
        connect(&monitor1, SIGNAL(timeout()), SLOT(onMonitor1Timeout()));
        connect(&monitor2, SIGNAL(timeout()), SLOT(onMonitor2Timeout()));
        connect(&monitor3, SIGNAL(timeout()), SLOT(onMonitor3Timeout()));
    }
    else
        monitorLevel = 0;

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

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

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

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

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

    focusHumidityButtonTimer.setSingleShot(true);
    focusHumidityButtonTimer.setInterval(3000);
    connect(&focusHumidityButtonTimer, SIGNAL(timeout()), SLOT(focusHumidityButton()));

    focusTempButtonTimer.setSingleShot(true);
    focusTempButtonTimer.setInterval(3000);
    connect(&focusTempButtonTimer, SIGNAL(timeout()), SLOT(focusTempButton()));

    focusTimeButtonTimer.setSingleShot(true);
    focusTimeButtonTimer.setInterval(3000);
    connect(&focusTimeButtonTimer, SIGNAL(timeout()), SLOT(focusTimeButton()));

    focusInterTempButtonTimer.setSingleShot(true);
    focusInterTempButtonTimer.setInterval(3000);
    connect(&focusInterTempButtonTimer, SIGNAL(timeout()), SLOT(focusInterTempButton()));

    connect(ui->humiditySlider, SIGNAL(sliderMoved(int)), &focusHumidityButtonTimer, SLOT(start()));
    connect(ui->tempSlider, SIGNAL(sliderMoved(int)), &focusTempButtonTimer, SLOT(start()));
    connect(ui->timeSlider, SIGNAL(sliderMoved(int)), &focusTimeButtonTimer, SLOT(start()));
    connect(ui->interTempSlider, SIGNAL(sliderMoved(int)), &focusInterTempButtonTimer, SLOT(start()));

    connect(ui->humiditySlider, SIGNAL(sliderPressed()), SLOT(updateView()));
    connect(ui->tempSlider, SIGNAL(sliderPressed()), SLOT(updateView()));
    connect(ui->timeSlider, SIGNAL(sliderPressed()), SLOT(updateView()));
    connect(ui->interTempSlider, SIGNAL(sliderPressed()), SLOT(updateView()));

    connect(oven, SIGNAL(changed(Oven*)), this, SLOT(onOvenUpdated(Oven*)));
    oven->setDefault(mode);

    connect(&updateViewTimer, SIGNAL(timeout()), SLOT(updateView()));
    updateViewTimer.start(100);

    foreach (QPushButton *button, findChildren<QPushButton *>())
        if (button != ui->runStopButton)
            connect(button, &QPushButton::pressed, SoundPlayer::playClick);

    QTimer::singleShot(0, this, SLOT(setupAnimation()));

    setFocus();
}

ManualCookWindow::ManualCookWindow(QWidget *parent, ManualCookSetting setting)
    : ManualCookWindow(parent, setting.mode)
{
    oven->setHumidity(setting.humidity);
    oven->setTemp(setting.temp);
    oven->setTime(setting.time);
    oven->setFan(setting.fan);
    oven->setInterTempEnabled(setting.coreTempEnabled);
    oven->setInterTemp(setting.coreTemp);

    startCookingTimer.start();

    onOvenUpdated(oven);
}

ManualCookWindow::~ManualCookWindow()
{
    stop();

    delete ui;
}

void ManualCookWindow::keyPressEvent(QKeyEvent *event)
{
    switch (event->key())
    {
    case 0x01000032:    // Turn left
        onEncoderLeft();
        break;
    case 0x01000031:    // Push
        if (focusWidget() != this)
        {
            pushed = focusWidget();

            if (pushed == ui->humidityButton)
                on_humidityButton_pressed();
            else if (pushed == ui->tempButton)
                on_tempButton_pressed();

        }
        break;
    case 0x01000030:    // Turn right
        onEncoderRight();
        break;
    }
}

void ManualCookWindow::keyReleaseEvent(QKeyEvent *event)
{
    switch (event->key())
    {
    case 0x01000032:    // Turn left
        onEncoderLeft();
        break;
    case 0x01000031:    // Push
        if (pushed == ui->humidityButton)
            on_humidityButton_released();
        else if (pushed == ui->tempButton)
            on_tempButton_released();

        if (focusWidget() == pushed)
            onEncoderClicked(pushed);

        pushed = NULL;
        break;
    case 0x01000030:    // Turn right
        onEncoderRight();
        break;
    }
}

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::updateView()
{
    switch (oven->mode())
    {
    case Define::DryMode:
        if (ui->steamButton->isChecked())
            ui->steamButton->setChecked(false);
        if (ui->combiButton->isChecked())
            ui->combiButton->setChecked(false);
        if (!ui->dryheatButton->isChecked())
            ui->dryheatButton->setChecked(true);
        break;
    case Define::SteamMode:
        if (!ui->steamButton->isChecked())
            ui->steamButton->setChecked(true);
        if (ui->combiButton->isChecked())
            ui->combiButton->setChecked(false);
        if (ui->dryheatButton->isChecked())
            ui->dryheatButton->setChecked(false);
        break;
    case Define::CombiMode:
        if (ui->steamButton->isChecked())
            ui->steamButton->setChecked(false);
        if (!ui->combiButton->isChecked())
            ui->combiButton->setChecked(true);
        if (ui->dryheatButton->isChecked())
            ui->dryheatButton->setChecked(false);
        break;
    default:
        break;
    }

    QWidget *focused = focusWidget();
    ui->humidityButton->setChecked(focused == ui->humiditySlider);
    ui->tempButton->setChecked(focused == ui->tempSlider);
    ui->timeButton->setChecked(focused == ui->timeSlider);

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

    if (humidity != lastViewHumidity)
    {
        lastViewHumidity = humidity;

        bool old = ui->humiditySlider->blockSignals(true);
        if (ui->humiditySlider->sliderPosition() != humidity)
            ui->humiditySlider->setValue(humidity);
        ui->humiditySlider->setEnabled(oven->mode() == Define::CombiMode);
        ui->humiditySlider->blockSignals(old);

        ui->humidityLabel->setText(QString("%1%").arg(humidity));
    }

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

    if (temp != lastViewTemp)
    {
        lastViewTemp = temp;

        ui->tempLabel->setText(Stringer::temperature(temp, Stringer::fontSize14));
    }

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

    int msecs = oven->msecs();
    if (ui->timeSlider->isSliderMoved())
        ui->timeLabel->setText(Stringer::remainingTime(sliderToTime(ui->timeSlider->sliderPosition()) * 1000, Stringer::fontSize14));
    else
        ui->timeLabel->setText(Stringer::remainingTime(msecs, Stringer::fontSize14));

    if (focusWidget() != ui->timeSlider)
    {
        bool old = ui->timeSlider->blockSignals(true);
        ui->timeSlider->setSliderPosition(timeToSlider(msecs / 1000));
        ui->timeSlider->blockSignals(old);
    }

    int interTemp;
    if (ui->interTempSlider->isSliderDown() || focusWidget() == ui->interTempSlider)
        interTemp = ui->interTempSlider->sliderPosition();
    else
        interTemp = oven->interTemp();

    QString interTempButtonStyleSheet("\
QPushButton\
{ image: url(%1); }\
QPushButton:pressed,\
QPushButton:focus\
{ image: url(:/images/slider_icon/011_icon_04_active.png); }\
QPushButton:checked\
{ image: url(:/images/slider_icon/core_temp_ov.png); }");

    bool interTempEnabled = oven->interTempEnabled();
    if (interTempEnabled != lastViewInterTempEnabled)
    {
        lastViewInterTempEnabled = interTempEnabled;
        if (interTempEnabled)
            ui->interTempButton->setStyleSheet(interTempButtonStyleSheet.arg(":/images/slider_icon/core_temp_enabled.png"));
        else
            ui->interTempButton->setStyleSheet(interTempButtonStyleSheet.arg(":/images/slider_icon/core_temp.png"));
    }

    ui->interTempButton->setChecked(focusWidget() == ui->interTempSlider);


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

    if (interTempEnabled)
        ui->interTempLabel->setText(Stringer::temperature(interTemp, Stringer::fontSize14));
    else
        ui->interTempLabel->setText(Stringer::unusedTemperature(Stringer::fontSize14));

    ui->runStopButton->setChecked(oven->cooking());

    if (showFrontButtons)
    {
        ui->preheatButton->show();
        ui->damperButton->show();
        ui->humidificationButton->show();
        if (oven->cooking())
            ui->repeatButton->show();
        else
            ui->repeatButton->hide();

        ui->cooldownButton->hide();
        ui->fanButton->hide();
        ui->reserveButton->hide();
        ui->favoriteButton->hide();
    }
    else
    {
        ui->preheatButton->hide();
        ui->damperButton->hide();
        ui->humidificationButton->hide();
        ui->repeatButton->hide();

        ui->cooldownButton->show();
        ui->fanButton->show();
        if (oven->cooking())
        {
            ui->reserveButton->hide();
            ui->favoriteButton->hide();
        }
        else
        {
            ui->reserveButton->show();
            ui->favoriteButton->show();
        }
    }

    bool damper = oven->damper();
    ui->damperButton->setChecked(damper);

    bool humidification = oven->humidification();
    ui->humidificationButton->setChecked(humidification);

    QString fanStyleSheet("\
QPushButton { background-image: url(%1); }\
QPushButton:focus { background-image: url(%2); }");

    int fan = oven->fan();
    if (fan != lastViewFan)
    {
        lastViewFan = fan;

        switch (fan)
        {
        case 1:
            ui->fanButton->setStyleSheet(fanStyleSheet
                                         .arg(":/images/manual_button/fan_1.png")
                                         .arg(":/images/manual_button/013_sys_icon_06_active.png"));
            break;
        case 2:
            ui->fanButton->setStyleSheet(fanStyleSheet
                                         .arg(":/images/manual_button/fan_2.png")
                                         .arg(":/images/manual_button/013_sys_icon_06_01_active.png"));
            break;
        case 3:
            ui->fanButton->setStyleSheet(fanStyleSheet
                                         .arg(":/images/manual_button/fan_3.png")
                                         .arg(":/images/manual_button/013_sys_icon_06_02_active.png"));
            break;
        case 4:
            ui->fanButton->setStyleSheet(fanStyleSheet
                                         .arg(":/images/manual_button/fan_4.png")
                                         .arg(":/images/manual_button/013_sys_icon_06_03_active.png"));
            break;
        case 5:
            ui->fanButton->setStyleSheet(fanStyleSheet
                                         .arg(":/images/manual_button/fan_5.png")
                                         .arg(":/images/manual_button/013_sys_icon_06_04_active.png"));
            break;
        default:
            ui->fanButton->setStyleSheet(fanStyleSheet
                                         .arg(":/images/manual_button/fan_6.png")
                                         .arg(":/images/manual_button/013_sys_icon_06_active.png"));
            break;
        }
    }

    ui->repeatButton->setChecked(repeat);

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

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

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

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

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

void ManualCookWindow::onOvenUpdated(Oven *oven)
{
    updateView();

    if (oven->interTempEnabled() && oven->currentInterTemp() >= oven->interTemp())
        stop();

    if (repeat && !oven->cooking())
    {
        repeat = false;

        oven->setMode(repeatSetting.mode);
        oven->setHumidity(repeatSetting.humidity);
        oven->setTemp(repeatSetting.temp);
        oven->setTime(repeatSetting.time);
        oven->setInterTempEnabled(repeatSetting.coreTempEnabled);
        oven->setInterTemp(repeatSetting.coreTemp);

        updateView();
    }
    else if (lastCheckedCooking && !oven->cooking()){
        if ((oven->interTempEnabled() && oven->currentInterTemp() >= oven->interTemp())
                || oven->time() == 0)
        {
            lastCheckedCooking = oven->cooking();
            emit done();
        }
    }

    lastCheckedCooking = oven->cooking();

    if (oven->paused() && oven->door())
    {
        if (monitorLevel > 0 && !monitorTriggered)
        {
            monitorTriggered = true;
            monitor1.start();
        }
    }

    if (monitorTriggered && !oven->door())
    {
        monitorTriggered = false;
        monitor1.stop();
        monitor2.stop();
        monitor3.stop();
    }
}

void ManualCookWindow::setOvenDefault(Define::Mode mode)
{
    stop();

    oven->setDefault(mode);
}

void ManualCookWindow::start()
{
    if (oven->cooking())
        return;

    if (oven->time() > 0)
    {
        SoundPlayer::playStart();

        if (startCookingTimer.isActive())
            startCookingTimer.stop();

        oven->startCooking();

        ManualCookSetting s;
        s.mode = oven->mode();
        s.humidity = oven->humidity();
        s.temp = oven->temp();
        s.time = oven->time();
        s.fan = oven->fan();
        s.coreTempEnabled = oven->interTempEnabled();
        s.coreTemp = oven->interTemp();

        CookHistory::record(s);

        if (monitorLevel > 0 && oven->door())
        {
            monitorTriggered = true;
            monitor1.start();
        }
        else
            monitorTriggered = false;
    }
}

void ManualCookWindow::stop()
{
    if (oven->cooking())
        SoundPlayer::playStop();

    oven->stop();
    startCookingTimer.stop();
}

void ManualCookWindow::addFavorite()
{
    ManualCookSetting s;
    s.mode = oven->mode();
    s.humidity = oven->humidity();
    s.temp = oven->temp();
    s.time = oven->time();
    s.fan = oven->fan();
    s.coreTempEnabled = oven->interTempEnabled();
    s.coreTemp = oven->interTemp();

    FavoriteNamePopup *p = new FavoriteNamePopup(this, s);
    p->showFullScreen();
}

void ManualCookWindow::jumpConfig()
{
    stop();

    ConfigWindow *w = new ConfigWindow(MainWindow::getInstance());
    w->setWindowModality(Qt::WindowModal);
    w->showFullScreen();
    w->raise();

    MainWindow::jump(w);
}

void ManualCookWindow::jumpFavorites()
{
    stop();

    PrimeWindow *w = new PrimeWindow(MainWindow::getInstance());
    w->setWindowModality(Qt::WindowModal);
    w->listFavorites();
    w->showFullScreen();
    w->raise();

    MainWindow::jump(w);
}

void ManualCookWindow::jumpWash()
{
    stop();

    WashWindow *w = new WashWindow(MainWindow::getInstance());
    w->setWindowModality(Qt::WindowModal);
    w->showFullScreen();
    w->raise();

    MainWindow::jump(w);
}

void ManualCookWindow::onMonitor1Timeout()
{
    SoundPlayer::playError1();
    ErrorPopupDlg *d = new ErrorPopupDlg(this, tr("문을 닫아주세요"), tr("조리 중 문 열림 시간 모니터링 1단계"));
    d->showFullScreen();

    if (monitorLevel > 1)
        monitor2.start();
}

void ManualCookWindow::onMonitor2Timeout()
{
    SoundPlayer::playError1();
    ErrorPopupDlg *d = new ErrorPopupDlg(this, tr("문을 닫아주세요"), tr("조리 중 문 열림 시간 모니터링 2단계"));
    d->showFullScreen();

    if (monitorLevel > 2)
        monitor3.start();
}

void ManualCookWindow::onMonitor3Timeout()
{
    SoundPlayer::playError1();
    ErrorPopupDlg *d = new ErrorPopupDlg(MainWindow::getInstance(), tr("문이 오래 열려있어 조리가 취소되었습니다"), tr("조리 중 문 열림 시간 모니터링 3단계"));
    d->showFullScreen();
    close();
}

void ManualCookWindow::onEncoderLeft()
{
    QWidget *focused = focusWidget();
    if (focused == NULL)
        focusPreviousChild();
    else if (focused == this || focused->inherits("QPushButton"))
    {
        focusPreviousChild();
        focused = focusWidget();

        if (focused == ui->steamButton)
        {
            if (oven->mode() == Define::SteamMode)
                focusPreviousChild();
        }
        else if (focused == ui->combiButton)
        {
            if (oven->mode() == Define::CombiMode)
                focusPreviousChild();
        }
        else if (focused == ui->dryheatButton)
        {
            if (oven->mode() == Define::DryMode)
                focusPreviousChild();
        }
    }
}

void ManualCookWindow::onEncoderRight()
{
    QWidget *focused = focusWidget();
    if (focused == NULL)
        focusNextChild();
    else if (focused == this)
    {
        switch (oven->mode())
        {
        case Define::DryMode:
        case Define::SteamMode:
            ui->tempButton->setFocus();
            break;
        default:
            ui->humidityButton->setFocus();
        }
    }
    else if (focused->inherits("QPushButton"))
    {
        focusNextChild();
        focused = focusWidget();

        if (focused == ui->steamButton)
        {
            if (oven->mode() == Define::SteamMode)
                focusNextChild();
        }
        else if (focused == ui->combiButton)
        {
            if (oven->mode() == Define::CombiMode)
                focusNextChild();
        }
        else if (focused == ui->dryheatButton)
        {
            if (oven->mode() == Define::DryMode)
                focusNextChild();
        }
    }
}

void ManualCookWindow::onEncoderClicked(QWidget *clicked)
{
    QWidget *focused = clicked;
    if (focused == NULL)
        return;

    if (focused->inherits("QPushButton"))
    {
        QPushButton *pb = qobject_cast<QPushButton *>(focused);
        if (pb)
        {
            pb->click();

            if (pb == ui->steamButton || pb == ui->dryheatButton)
                ui->tempButton->setFocus();
            else if (pb == ui->combiButton)
                ui->humidityButton->setFocus();
        }
    }
    else if (focused->inherits("Slider"))
    {
        Slider *slider = qobject_cast<Slider *>(focused);
        if (slider)
        {
            if (slider->value() != slider->sliderPosition())
                slider->setValue(slider->sliderPosition());

            if (slider == ui->humiditySlider)
                ui->humidityButton->setFocus();
            else if (slider == ui->tempSlider)
                ui->tempButton->setFocus();
            else if (slider == ui->timeSlider)
                ui->timeButton->setFocus();
            else if (slider == ui->interTempSlider)
                ui->interTempButton->setFocus();
        }
    }
}

void ManualCookWindow::focusHumidityButton()
{
    if (focusWidget() == ui->humiditySlider)
    {
        oven->setHumidity(ui->humiditySlider->value());
        ui->humidityButton->setFocus();
    }
}

void ManualCookWindow::focusTempButton()
{
    if (focusWidget() == ui->tempSlider)
    {
        oven->setTemp(ui->tempSlider->value());
        ui->tempButton->setFocus();
    }
}

void ManualCookWindow::focusTimeButton()
{
    if (focusWidget() == ui->timeSlider)
    {
        if (ui->timeSlider->isSliderMoved())
            oven->setTime(sliderToTime(ui->timeSlider->value()));
        ui->timeButton->setFocus();
    }
}

void ManualCookWindow::focusInterTempButton()
{
    if (focusWidget() == ui->interTempSlider)
    {
        oven->setInterTemp(ui->interTempSlider->value());
        ui->interTempButton->setFocus();
    }
}

void ManualCookWindow::focusAgain()
{
    if (focused)
    {
        focused->setFocus();
        focused = NULL;
    }
}

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_humidityButton_clicked()
{
    ui->humiditySlider->setFocus();

    focusHumidityButtonTimer.start();
}

void ManualCookWindow::on_tempButton_clicked()
{
    ui->tempSlider->setFocus();

    focusTempButtonTimer.start();
}

void ManualCookWindow::on_timeButton_clicked()
{
    ui->timeSlider->setFocus();

    focusTimeButtonTimer.start();
}

void ManualCookWindow::on_interTempButton_clicked()
{
    if (oven->interTempEnabled())
        oven->setInterTempEnabled(false);
    else
    {
        CoreTempSettingPopup *p = new CoreTempSettingPopup(this);
        p->show();

        focused = ui->interTempButton;
        connect(p, SIGNAL(destroyed(QObject*)), SLOT(focusAgain()));
    }
}

void ManualCookWindow::on_runStopButton_clicked()
{
    if (oven->cooking())
        stop();
    else if (oven->time() > 0)
        start();
    else
        SoundPlayer::playClick();

    updateView();
}

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

    focused = ui->preheatButton;
    connect(p, SIGNAL(destroyed(QObject*)), SLOT(focusAgain()));
}

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()
{
    if (repeat)
    {
        repeat = false;
        updateView();
    }
    else
    {
        repeat = true;
        updateView();

        repeatSetting.mode = oven->mode();
        repeatSetting.humidity = oven->humidity();
        repeatSetting.temp= oven->temp();
        repeatSetting.time = oven->time();
        repeatSetting.coreTempEnabled = oven->interTempEnabled();
        repeatSetting.coreTemp = oven->interTemp();
    }
}

void ManualCookWindow::on_cooldownButton_clicked()
{
    startCookingTimer.stop();

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

    focused = ui->cooldownButton;
    connect(p, SIGNAL(destroyed(QObject*)), SLOT(focusAgain()));
}

void ManualCookWindow::on_reserveButton_clicked()
{
    if (oven->time() > 0)
    {
        startCookingTimer.stop();

        ReserveTimePopup *p = new ReserveTimePopup(this);
        connect(p, SIGNAL(timeout()), SLOT(start()));
        connect(p, SIGNAL(canceled()), &startCookingTimer, SLOT(start()));
        p->showFullScreen();

        focused = ui->reserveButton;
        connect(p, SIGNAL(destroyed(QObject*)), SLOT(focusAgain()));
    }
}

void ManualCookWindow::on_favoriteButton_clicked()
{
//    if (oven->cooking())
//        return;

//    ConfirmPopup *p = new ConfirmPopup(this, tr("즐겨찾기 항목에 추가하시겠습니까?"));
//    p->showFullScreen();

//    focused = ui->favoriteButton;
//    connect(p, SIGNAL(rejected()), SLOT(focusAgain()));
//    connect(p, SIGNAL(accepted()), SLOT(addFavorite()));

//    if (startCookingTimer.isActive())
//    {
//        startCookingTimer.stop();
//        connect(p, SIGNAL(rejected()), &startCookingTimer, SLOT(start()));
//    }
}

void ManualCookWindow::on_goFrontStackButton_clicked()
{
    showFrontButtons = !showFrontButtons;

    updateView();
}

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

void ManualCookWindow::on_configButton_clicked()
{
    if (oven->cooking())
    {
        ConfirmPopup *p = new ConfirmPopup(this, tr("요리가 중단되고 환경 설정 모드로 들어갑니다. 진행할까요?"));
        p->showFullScreen();

        connect(p, SIGNAL(accepted()), SLOT(jumpConfig()));

        focused = ui->configButton;
        connect(p, SIGNAL(destroyed(QObject*)), SLOT(focusAgain()));
    }
    else
    {
        ConfigWindow *w = new ConfigWindow(MainWindow::getInstance());
        w->setWindowModality(Qt::WindowModal);
        w->showFullScreen();
        w->raise();

        MainWindow::jump(w);
    }
}

void ManualCookWindow::on_favoritesButton_clicked()
{
//    if (oven->cooking())
//    {
//        ConfirmPopup *p = new ConfirmPopup(this, tr("요리가 중단되고 즐겨찾기 모드로 들어갑니다. 진행할까요?"));
//        p->showFullScreen();

//        connect(p, SIGNAL(accepted()), SLOT(jumpFavorites()));

//        focused = ui->favoritesButton;
//        connect(p, SIGNAL(destroyed(QObject*)), SLOT(focusAgain()));
//    }
//    else
//    {
//        PrimeWindow *w = new PrimeWindow(MainWindow::getInstance());
//        w->setWindowModality(Qt::WindowModal);
//        w->listFavorites();
//        w->showFullScreen();
//        w->raise();

//        MainWindow::jump(w);
//    }
}

void ManualCookWindow::on_washButton_clicked()
{
    if (oven->cooking())
    {
        ConfirmPopup *p = new ConfirmPopup(this, tr("요리가 중단되고 자동 세척 모드로 들어갑니다. 진행할까요?"));
        p->showFullScreen();

        connect(p, SIGNAL(accepted()), SLOT(jumpWash()));

        focused = ui->washButton;
        connect(p, SIGNAL(destroyed(QObject*)), SLOT(focusAgain()));
    }
    else
    {
        WashWindow *w = new WashWindow(MainWindow::getInstance());
        w->setWindowModality(Qt::WindowModal);
        w->showFullScreen();
        w->raise();

        MainWindow::jump(w);
    }
}

void ManualCookWindow::on_helpButton_clicked()
{

}

void ManualCookWindow::on_timeSlider_valueChanged()
{
    oven->setTime(sliderToTime(ui->timeSlider->value()));
}

int ManualCookWindow::sliderToTime(int value)
{
    if (value <= 180)
        return value * 60;
    if (value <= 270)
        return 180 * 60 + (value - 180) * 2 * 60;
    return 360 * 60 + (value - 270) * 15 * 60;
}

int ManualCookWindow::timeToSlider(int secs)
{
    if (secs <= 180 * 60)
        return qCeil((qreal) secs / 60);
    if (secs <= 360 * 60)
        return 180 + qCeil((qreal) (secs - 180 * 60) / 2 / 60);
    return 270 + qCeil((qreal) (secs - 360 * 60) / 15 / 60);
}