#include "multicookwindow.h"
#include "ui_multicookwindow.h"

#include <QDebug>
#include <QKeyEvent>

#include "multimanualcook.h"
#include "multiautocook.h"
#include "multicookrecorder.h"
#include "multicookselectionwindow.h"
#include "oven.h"
#include "stringer.h"
#include "confirmpopup.h"
#include "configwindow.h"
#include "washwindow.h"
#include "mainwindow.h"
#include "manualviewerdlg.h"

MultiCookWindow::MultiCookWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MultiCookWindow)
{
    ui->setupUi(this);
    setAttribute(Qt::WA_DeleteOnClose);

    controller = new MultiCookController(this);
    container = new MultiCookContainer(this);
    controller->setContainer(container);
    ui->view->setContainer(container);
    ui->view->setTimeBar(ui->bar);

    connect(ui->view, SIGNAL(clicked(int)), SLOT(handleViewClick(int)));


    buttons.append(ui->selectButton_1);
    buttons.append(ui->selectButton_2);
    buttons.append(ui->selectButton_3);
    buttons.append(ui->selectButton_4);
    buttons.append(ui->selectButton_5);
    buttons.append(ui->selectButton_6);
    buttons.append(ui->selectButton_7);
    buttons.append(ui->selectButton_8);
    buttons.append(ui->selectButton_9);
    buttons.append(ui->selectButton_10);

    recentButtons.append(ui->recentButton_1);
    recentButtons.append(ui->recentButton_2);
    recentButtons.append(ui->recentButton_3);
    recentButtons.append(ui->recentButton_4);
    recentButtons.append(ui->recentButton_5);
    recentButtons.append(ui->recentButton_6);

    mode = Define::InvalidMode;

    lastClickedEmptyButton = -1;
    lastClickedCookButton = -1;
    lastClickedRecentCook = -1;
    trashClicked = false;

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

    setFocus();

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

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

}

MultiCookWindow::~MultiCookWindow()
{
    delete ui;

    Oven::getInstance()->stop();
}

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

void MultiCookWindow::keyReleaseEvent(QKeyEvent *event)
{
    switch (event->key())
    {
    case 0x01000032:    // Turn left
        onEncoderLeft();
        break;
    case 0x01000031:    // Push
        if (focusWidget() == pushed)
            onEncoderClicked(pushed);

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

void MultiCookWindow::updateView()
{
    Oven *oven = Oven::getInstance();
    if (controller->requireOpen() && !oven->door())
    {
        ui->blockingArea->setEnabled(false);
        ui->closeDoorAnimationArea->hide();
        ui->openDoorAnimationArea->show();
    }
    else if (controller->requireClose() && oven->door())
    {
        ui->blockingArea->setEnabled(false);
        ui->closeDoorAnimationArea->show();
        ui->openDoorAnimationArea->hide();
    }
    else
    {
        ui->blockingArea->setEnabled(true);
        ui->closeDoorAnimationArea->hide();
        ui->openDoorAnimationArea->hide();
    }


    QTime currentTime = QTime::currentTime();
    ui->showNowButton->setText(QString("%1:%2")
                               .arg(currentTime.hour(), 2, 10, QLatin1Char('0'))
                               .arg(currentTime.minute(), 2, 10, QLatin1Char('0')));

    QString infoText;

    for (int i = 0; i < 10; i++)
    {
        QPushButton *button = buttons.at(i);

        MultiCook *cook = container->at(i);
        if (cook == Q_NULLPTR)
            button->setText("-");
        else
        {
            if (cook->remainingTime() <= 0)
            {
                if (!infoText.isEmpty())
                    infoText += "\n";

                infoText += tr("%1번 단 요리(%2)가 종료되었습니다")
                        .arg(i + 1).arg(cook->name());
            }

            button->setText(Stringer::time(cook->remainingTime()));
        }
    }

    if (!infoText.isEmpty())
    {
        ui->upperStack->setCurrentIndex(2);
        ui->info->setText(infoText);
    }
    else if (ui->upperStack->currentIndex() == 2)
        ui->upperStack->setCurrentIndex(0);

    if (ui->upperStack->currentIndex() == 1)
        updateRecents();
}

void MultiCookWindow::updateRecents()
{
    if (recents.size() > 0)
    {
        if (recents.size() > 6)
        {
            int currentPage = ui->pageIndicator->currentIndex();
            int from = currentPage * 6;
            int to = qMin(6, recents.size() - from) + from;

            for (int i = from; i < to; i++)
            {
                QPushButton *b = recentButtons.at(i - from);
                b->show();
                b->setText(recents.at(i)->name());
            }

            for (int i = to - from; i < 6; i++)
                recentButtons.at(i)->hide();

            ui->showNextPageButton->show();
            ui->showPrevPageButton->show();
            ui->pageIndicator->show();
        }
        else
        {
            int max = qMin(6, recents.size());
            for (int i = 0; i < max; i++)
            {
                QPushButton *b = recentButtons.at(i);
                b->show();
                b->setText(recents.at(i)->name());
            }

            for (int i = max; i < 6; i++)
                recentButtons.at(i)->hide();

            ui->showNextPageButton->hide();
            ui->showPrevPageButton->hide();
            ui->pageIndicator->hide();
        }
    }
    else
    {
        foreach (QPushButton *b, recentButtons)
            b->hide();

        ui->showNextPageButton->hide();
        ui->showPrevPageButton->hide();
        ui->pageIndicator->hide();
    }
}

void MultiCookWindow::handleViewClick(int slot)
{
    buttons.at(slot)->setFocus();

    handleButtonClick(slot);
}

void MultiCookWindow::handleButtonClick(int button)
{
    if (lastClickedCookButton != -1)
    {
        MultiCook *cook = container->at(lastClickedCookButton);
        if (cook)
            cook->setTime();

        lastClickedCookButton = -1;
    }

    MultiCook *cook = container->at(button);
    if (cook)
    {
        if (trashClicked)
        {
            trashClicked = false;
            container->remove(button);
            cook->deleteLater();
        }
        else
            lastClickedCookButton = button;
    }
    else
    {
        if (lastClickedRecentCook != -1)
        {
            addCook(button, recents.at(lastClickedRecentCook)->clone(this));

            lastClickedRecentCook = -1;
        }
        else
        {
            lastClickedEmptyButton = button;

            ui->upperStack->setCurrentIndex(0);
            setFocus();

            selectCook();
        }
    }
}

void MultiCookWindow::handleRecentButtonClick(int button)
{
    lastClickedRecentCook = button + ui->pageIndicator->currentIndex() * 6;
}

void MultiCookWindow::selectCook()
{
    MultiCookSelectionWindow *w = new MultiCookSelectionWindow(this);

    if (mode != Define::InvalidMode)
        w->setMode(mode);

    w->setWindowModality(Qt::WindowModal);
    w->showFullScreen();
    w->raise();

    connect(w, SIGNAL(selected(MultiCook*)), SLOT(onCookSelected(MultiCook*)));
}

void MultiCookWindow::onCookSelected(MultiCook *cook)
{
    cook->setParent(this);

    if (lastClickedEmptyButton != -1)
    {
        addCook(lastClickedEmptyButton, cook);
        lastClickedEmptyButton = -1;
    }
}

void MultiCookWindow::showRecents()
{
    recents = MultiCookRecorder::list();

    ui->upperStack->setCurrentIndex(1);
    ui->pageIndicator->setMaximum(recents.size() / 6);
    ui->pageIndicator->setCurrentIndex(0);

    updateRecents();
}

void MultiCookWindow::showClock()
{
    ui->upperStack->setCurrentIndex(0);
}

void MultiCookWindow::addCook(int slot, MultiCook *cook)
{
    mode = cook->mode();
    MultiCookRecorder::record(cook);
    container->add(slot, cook);
}

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

    MainWindow::jump(w);
}

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

    MainWindow::jump(w);
}

void MultiCookWindow::on_showPrevButton_clicked()
{
    ui->view->showPrev();
}

void MultiCookWindow::on_showNowButton_clicked()
{
    ui->view->showNow();
}

void MultiCookWindow::on_showNextButton_clicked()
{
    ui->view->showNext();
}

void MultiCookWindow::on_showFavoritesButton_clicked()
{
    if (ui->upperStack->currentIndex() == 0)
        showRecents();
    else
        showClock();
}

void MultiCookWindow::on_backButton_clicked()
{
    if (container->isEmpty() || container->isFinished())
    {
        close();
    }
    else
    {
        ConfirmPopup *p = new ConfirmPopup(this, tr("요리를 취소하시겠습니까?"));
        p->showFullScreen();

        connect(p, SIGNAL(accepted()), SLOT(close()));
    }
}

void MultiCookWindow::on_configButton_clicked()
{
    if (container->isEmpty() || container->isFinished())
    {
        jumpConfig();
    }
    else
    {
        ConfirmPopup *p = new ConfirmPopup(this, tr("요리를 취소하시겠습니까?"));
        p->showFullScreen();

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

void MultiCookWindow::on_washButton_clicked()
{
    if (container->isEmpty() || container->isFinished())
    {
        jumpConfig();
    }
    else
    {
        ConfirmPopup *p = new ConfirmPopup(this, tr("요리를 취소하시겠습니까?"));
        p->showFullScreen();

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

void MultiCookWindow::on_deleteButton_clicked()
{
    trashClicked = true;
}

void MultiCookWindow::on_helpButton_clicked()
{
    ManualViewerDlg* dlg = new ManualViewerDlg(this);
    dlg->showFullScreen();
    dlg->raise();
}

void MultiCookWindow::onEncoderLeft()
{
    MultiCook *c = Q_NULLPTR;

    if (lastClickedCookButton != -1)
        c = container->at(lastClickedCookButton);

    if (c)
        c->decreaseTime();
    else
        focusPreviousChild();
}

void MultiCookWindow::onEncoderRight()
{
    MultiCook *c = Q_NULLPTR;

    if (lastClickedCookButton != -1)
        c = container->at(lastClickedCookButton);

    if (c)
        c->increaseTime();
    else
        focusNextChild();
}

void MultiCookWindow::onEncoderClicked(QWidget *clicked)
{
    MultiCook *c = Q_NULLPTR;

    if (lastClickedCookButton != -1)
    {
        c = container->at(lastClickedCookButton);

        lastClickedCookButton = -1;
    }

    if (c)
        c->setTime();
    else
    {
        QPushButton *b = qobject_cast<QPushButton *>(clicked);
        if (b)
            b->click();
    }
}

void MultiCookWindow::on_selectButton_1_clicked()
{
    handleButtonClick(0);
}

void MultiCookWindow::on_selectButton_2_clicked()
{
    handleButtonClick(1);
}

void MultiCookWindow::on_selectButton_3_clicked()
{
    handleButtonClick(2);
}

void MultiCookWindow::on_selectButton_4_clicked()
{
    handleButtonClick(3);
}

void MultiCookWindow::on_selectButton_5_clicked()
{
    handleButtonClick(4);
}

void MultiCookWindow::on_selectButton_6_clicked()
{
    handleButtonClick(5);
}

void MultiCookWindow::on_selectButton_7_clicked()
{
    handleButtonClick(6);
}

void MultiCookWindow::on_selectButton_8_clicked()
{
    handleButtonClick(7);
}

void MultiCookWindow::on_selectButton_9_clicked()
{
    handleButtonClick(8);
}

void MultiCookWindow::on_selectButton_10_clicked()
{
    handleButtonClick(9);
}

void MultiCookWindow::on_recentButton_1_clicked()
{
    handleRecentButtonClick(0);
}

void MultiCookWindow::on_recentButton_2_clicked()
{
    handleRecentButtonClick(1);
}

void MultiCookWindow::on_recentButton_3_clicked()
{
    handleRecentButtonClick(2);
}

void MultiCookWindow::on_recentButton_4_clicked()
{
    handleRecentButtonClick(3);
}

void MultiCookWindow::on_recentButton_5_clicked()
{
    handleRecentButtonClick(4);
}

void MultiCookWindow::on_recentButton_6_clicked()
{
    handleRecentButtonClick(5);
}

void MultiCookWindow::on_showPrevPageButton_clicked()
{
    ui->pageIndicator->setCurrentIndex(ui->pageIndicator->currentIndex() - 1);
    updateView();
}

void MultiCookWindow::on_showNextPageButton_clicked()
{
    ui->pageIndicator->setCurrentIndex(ui->pageIndicator->currentIndex() + 1);
    updateView();
}

void MultiCookWindow::on_homeButton_clicked()
{
    close();
}