/*
 *   This file is part of Dianara
 *   Copyright 2012-2019  JanKusanagi JRR <jancoding@gmx.com>
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the
 *   Free Software Foundation, Inc.,
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA .
 */

#include "pageselector.h"


PageSelector::PageSelector(QWidget *parent) : QWidget(parent)
{
    this->setWindowTitle(tr("Jump to page") + " - Dianara");
    this->setWindowIcon(QIcon::fromTheme("go-next-view-page",
                                         QIcon(":/images/button-next.png")));
    this->setWindowFlags(Qt::Dialog);
    this->setWindowModality(Qt::ApplicationModal);

    m_initialPage = 1;

    // Top
    m_messageLabel = new QLabel(tr("Page number:"), this);


    m_pageNumberSpinbox = new QSpinBox(this);
    m_pageNumberSpinbox->setRange(1, 1); // 1 to totalPages, but initially 1-1
    m_pageNumberSpinbox->setValue(1);
    connect(m_pageNumberSpinbox, &QAbstractSpinBox::editingFinished,
            this, &PageSelector::onPageNumberEntered);


    m_rangeLabel = new QLabel(this); // [ 1 ~ ### ]


    m_firstButton = new QPushButton(QIcon::fromTheme("go-first-view-page",
                                                     QIcon(":/images/button-previous.png")),
                                    tr("&First", "As in: first page"),
                                    this);
    connect(m_firstButton, &QAbstractButton::clicked,
            this, &PageSelector::setToFirstPage);

    m_lastButton = new QPushButton(QIcon::fromTheme("go-last-view-page",
                                                    QIcon(":/images/button-next.png")),
                                   tr("&Last", "As in: last page"),
                                   this);
    connect(m_lastButton, &QAbstractButton::clicked,
            this, &PageSelector::setToLastPage);


    // Middle
    m_newerButton = new QPushButton("< " + tr("Newer",
                                              "As in: newer pages"),
                                    this);
    connect(m_newerButton, &QAbstractButton::clicked,
            this, &PageSelector::decreasePage);

    m_pageNumberSlider = new QSlider(Qt::Horizontal, this);
    m_pageNumberSlider->setRange(1, 1);  // Initially
    m_pageNumberSlider->setValue(1);
    m_pageNumberSlider->setTickPosition(QSlider::TicksBelow);


    // Make spinbox and slider keep in sync
    connect(m_pageNumberSlider, &QAbstractSlider::valueChanged,
            m_pageNumberSpinbox, &QSpinBox::setValue);

    // And also enable/disable buttons depending on current page
    connect(m_pageNumberSpinbox, SIGNAL(valueChanged(int)), // Old-style, overload
            this, SLOT(onPageNumberChanged(int)));


    m_olderButton = new QPushButton(tr("Older",
                                       "As in: older pages") + " >",
                                    this);
    connect(m_olderButton, &QAbstractButton::clicked,
            this, &PageSelector::increasePage);



    // Bottom
    m_goButton = new QPushButton(QIcon::fromTheme("go-next-view-page",
                                                  QIcon(":/images/button-next.png")),
                                 "  " + tr("&Go") + " >>  ",
                                 this);
    m_goButton->setDisabled(true);
    connect(m_goButton, &QAbstractButton::clicked,
            this, &PageSelector::goToPage);


    m_closeButton = new QPushButton(QIcon::fromTheme("dialog-cancel",
                                                     QIcon(":/images/button-cancel.png")),
                                    tr("&Cancel"),
                                    this);
    connect(m_closeButton, &QAbstractButton::clicked,
            this, &QWidget::hide);

    m_bottomButtonBox = new QDialogButtonBox(this);
    m_bottomButtonBox->addButton(m_goButton,    QDialogButtonBox::AcceptRole);
    m_bottomButtonBox->addButton(m_closeButton, QDialogButtonBox::RejectRole);


    m_closeAction = new QAction(this);
    m_closeAction->setShortcut(QKeySequence(Qt::Key_Escape));
    connect(m_closeAction, &QAction::triggered,
            this, &QWidget::hide);
    this->addAction(m_closeAction);


    // Layout
    m_topLayout = new QHBoxLayout();
    m_topLayout->addWidget(m_messageLabel);
    m_topLayout->addSpacing(4);
    m_topLayout->addWidget(m_pageNumberSpinbox);
    m_topLayout->addSpacing(4);
    m_topLayout->addWidget(m_rangeLabel);
    m_topLayout->addSpacing(48);
    m_topLayout->addStretch(1);
    m_topLayout->addWidget(m_firstButton);
    m_topLayout->addWidget(m_lastButton);


    m_middleLayout = new QHBoxLayout();
    m_middleLayout->addWidget(m_newerButton);
    m_middleLayout->addSpacing(4);
    m_middleLayout->addWidget(m_pageNumberSlider);
    m_middleLayout->addSpacing(4);
    m_middleLayout->addWidget(m_olderButton);


    m_mainLayout = new QVBoxLayout();
    m_mainLayout->addLayout(m_topLayout);
    m_mainLayout->addSpacing(24);
    m_mainLayout->addStretch(1);
    m_mainLayout->addLayout(m_middleLayout);
    m_mainLayout->addStretch(2);
    m_mainLayout->addSpacing(32);
    m_mainLayout->addWidget(m_bottomButtonBox);
    this->setLayout(m_mainLayout);

    qDebug() << "PageSelector created";
}

PageSelector::~PageSelector()
{
    qDebug() << "PageSelector destroyed";
}

/*
 * To be called from TimeLine()
 *
 * Set current page based on current Timeline page, and total page count
 *
 */
void PageSelector::showForPage(int currentPage, int totalPageCount)
{
    m_initialPage = currentPage;

    m_pageNumberSpinbox->setRange(1, totalPageCount);
    m_pageNumberSpinbox->setValue(currentPage);

    m_pageNumberSlider->setRange(1, totalPageCount);
    // Value will get sync'ed from pageNumberSpinbox
    m_pageNumberSlider->setTickInterval(totalPageCount / 4); // One tick every 1/4th

    m_rangeLabel->setText(QString("[ 1 ~ %1 ]")
                          .arg(QLocale::system().toString(totalPageCount)));


    // Enable/disable needed buttons
    this->onPageNumberChanged(currentPage);

    this->show();
    m_pageNumberSpinbox->setFocus();
    m_pageNumberSpinbox->selectAll(); // So page numbers can be entered immediately
}


////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////// SLOTS /////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////


void PageSelector::setToFirstPage()
{
    m_pageNumberSpinbox->setValue(m_pageNumberSpinbox->minimum());
}


void PageSelector::setToLastPage()
{
    m_pageNumberSpinbox->setValue(m_pageNumberSpinbox->maximum());
}


void PageSelector::decreasePage()
{
    m_pageNumberSpinbox->setValue(m_pageNumberSpinbox->value() - 1);
}


void PageSelector::increasePage()
{
    m_pageNumberSpinbox->setValue(m_pageNumberSpinbox->value() + 1);
}


void PageSelector::goToPage()
{
    if (m_pageNumberSpinbox->value() != m_initialPage)
    {
        emit pageJumpRequested(m_pageNumberSpinbox->value());

        this->hide();
    }
}



void PageSelector::onPageNumberEntered()
{
    // If spinbox still has focus, it means ENTER was pressed
    if (m_pageNumberSpinbox->hasFocus())
    {
        this->goToPage();
    }

    // If not, it means focus went somewhere else,
    // which also causes editingFinished() to be emitted
}

/*
 * Keep slider bar in sync with spinbox, and enable/disable certain buttons
 * depending on currently selected page
 *
 */
void PageSelector::onPageNumberChanged(int selectedPage)
{
    m_pageNumberSlider->setValue(selectedPage);


    m_newerButton->setEnabled(selectedPage > 1);
    m_olderButton->setEnabled(selectedPage < m_pageNumberSpinbox->maximum());

    m_firstButton->setDisabled(selectedPage == 1);
    m_lastButton->setDisabled(selectedPage == m_pageNumberSpinbox->maximum());

    m_goButton->setDisabled(selectedPage == m_initialPage);
}

