#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>

#include "konapreviewimageview.h"

#include <QScrollBar>

/*
  NOTE #1: round results to get correct page maximum
  TODO: Too much to list here.
*/


MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    bottomPage = 1;
    insertAtBeginning = false;

    kc = new KonaClient(QDir::tempPath() + "/KonaClient", "/home/markus/Bilder/KonaChan/Cache", "/home/markus/Bilder/KonaChan/Archive");


    flowLayout = new FlowLayout;
    ui->listLayout->addLayout(flowLayout);

    connect(ui->scrollList->verticalScrollBar(), SIGNAL(valueChanged(int)),
            this, SLOT(onScroll(int)));


    search = new KonaSearch(kc, ui->txtSearch->text().toStdString().data(), 1);
    if (search->isDone()) searchFinished(search);
    else connect(search, SIGNAL(searchFinished(KonaSearch*)),
                 this, SLOT(searchFinished(KonaSearch*)));

    tags = new KonaTags(kc, "", RELATED_TAGS_AMOUNT);
    if (tags->isDone()) tagsFinished(tags);
    else connect(tags, SIGNAL(searchFinished(KonaTags*)),
                 this, SLOT(tagsFinished(KonaTags*)));

    relatedTags = new KonaRelatedTags(kc, "", "");
    connect(relatedTags, SIGNAL(searchFinished(KonaRelatedTags*)),
            this, SLOT(relatedTagsFinished(KonaRelatedTags*)));

    imageViewer = new ImageViewer(this);

    connect(imageViewer, SIGNAL(loadNext()),
            this, SLOT(jumpNext()));
    connect(imageViewer, SIGNAL(loadPrev()),
            this, SLOT(jumpPrev()));
}

MainWindow::~MainWindow()
{
    //search->deleteLater();
    //kc->deleteLater();
    delete ui;
}

void MainWindow::jumpPrev() {
    QList<KonaPreviewImageView*> kpiv = findChildren<KonaPreviewImageView*>();

    int x;
    for (x=0; x < kpiv.count(); x++) {
        if (x == 0) {
            qDebug() << "MainWindow: RELOAD <";
            ui->scrollList->verticalScrollBar()->setValue(1);
            ui->scrollList->verticalScrollBar()->setValue(0);
        }
        if (x < 1) { // Make sure we don't try to load non existent images
            qDebug() << "WARN! MainWindow: NOT LOADED YET OR END OF LIST";
        }
        else if (kpiv.at(x)->getKonaImage()->getId() == imageViewer->getCurrentId()) {
            qDebug() << "JUMP";
            showImage(kpiv.at(x-1)->getKonaImage());
            break;
        }
    }
    if (x == kpiv.count()) showImage(kpiv.at(0)->getKonaImage());
}

void MainWindow::jumpNext() {
    QList<KonaPreviewImageView*> kpiv = findChildren<KonaPreviewImageView*>();

    int x;
    for (x=0; x < kpiv.count(); x++) { // Loop through curerntly available images
        if (x + 1 + PRELOAD_AMOUNT == kpiv.count()) {
            qDebug() << "MainWindow: RELOAD >";
            ui->scrollList->verticalScrollBar()->setValue(ui->scrollList->verticalScrollBar()->maximum());
        }
        if (x + 1 >= kpiv.count()) { // Make sure we don't try to load non existent images
            qDebug() << "WARN! MainWindow: NOT LOADED YET OR END OF LIST";
        }
        else if (kpiv.at(x)->getKonaImage()->getId() == imageViewer->getCurrentId()) {
            showImage(kpiv.at(x+1)->getKonaImage());
            break;
        }
    }
    if (x == kpiv.count()) showImage(kpiv.at(0)->getKonaImage());
}

void MainWindow::onScroll(int value) {
    if (!search->isDone()) return; // Wait for current search to finish
    if (ui->scrollList->verticalScrollBar()->maximum() <= 0) return;
    if ((value/ui->scrollList->verticalScrollBar()->maximum())) {
        // hit lower end
            if (bottomPage <= ui->pageJumpNum->maximum()) { // TODO: might be wrong
                //ui->scrollList->verticalScrollBar()->setValue(1); //allow user to continue scrolling up
                insertAtBeginning = false;
                search->newSearch(currentSearch.toStdString().data(), ++bottomPage);
            }
    }
    else if (((float) value/ (float)ui->scrollList->verticalScrollBar()->maximum()) == 0){
        // hit upper end
        if (upperPage > 1) {// TODO: Sort the other way round on receive
            insertAtBeginning=true;
            search->newSearch(currentSearch.toStdString().data(), --upperPage);
        }
    }
}

void MainWindow::jumpToPage() {
    insertAtBeginning = false;
    ui->scrollList->verticalScrollBar()->setValue(1);
    upperPage = ui->pageJumpNum->value();
    bottomPage = ui->pageJumpNum->value();
    clearList();
    search->newSearch(currentSearch.toStdString().data(), ui->pageJumpNum->value());
}

void MainWindow::searchPools() {
    qDebug() << "POOLS not implemented yet!";
}

void MainWindow::searchPosts() {
    insertAtBeginning=false;
    ui->scrollList->verticalScrollBar()->setValue(0);
    ui->btnJump->setEnabled(false);
    upperPage = 1;
    bottomPage = 1;
    clearList();
    currentSearch = ui->txtSearch->text();
    search->newSearch(currentSearch.toStdString().data(), 1);

    if (ui->txtSearch->text() == "") {
        tags->newSearch(currentSearch);
    }
    else {
        relatedTags->newSearch(currentSearch);
    }
}


void MainWindow::searchFinished(KonaSearch *ks) {
    ui->btnJump->setEnabled(true);
    ui->pageJumpNum->setMaximum(ks->getTotalImages() / ITEMS_PER_SEARCH); // TODO: ROUND to get correct values (NOTE #1)
    ui->statusBar->showMessage("Search returned " + QString::number(ks->getTotalImages()) + " results.");

    for (int x=0; x < ks->getImages().count(); x++) {
        // Get the KonaImage
        KonaImage *ki = ks->getImages().at(x);

        // Check whether it already exists (shouldn't be possible but who knows...)
        QList<KonaPreviewImageView*> elEx = findChildren<KonaPreviewImageView*>(QString::number(ki->getId()));
        if (elEx.count() > 0) {
            qDebug() << "Main: searchFinished: Item already existed: " << ki->getId();
        }
        else {
            // Add new frame to list
            KonaPreviewImageView *temp = new KonaPreviewImageView();
            temp->setObjectName(QString::number(ki->getId()));
            if (insertAtBeginning) {
                flowLayout->insertWidgetAt(temp, 0); // Add @ beginning
            }
            else {
                flowLayout->addWidget(temp); // Add @ end
            }


            // Grab the new handle
            KonaPreviewImageView* kpiv = findChild<KonaPreviewImageView*>(QString::number(ki->getId()));

            // Update image
            connect(ki, SIGNAL(previewDownloaded(KonaImage*,QString)),
                    kpiv, SLOT(previewDownloaded(KonaImage*,QString)));

            connect(kpiv, SIGNAL(buttonClicked(KonaImage*)),
                    this, SLOT(downloadImage(KonaImage*)));

            connect(kpiv, SIGNAL(imageClicked(KonaImage*)),
                    this, SLOT(showImage(KonaImage*)));

            kpiv->setCaption("Download @ " + QString::number(ki->getWidth()) + " x " + QString::number(ki->getHeight())); //temp
            ki->DownloadPreview(); //Download!
        }
    }
}

void MainWindow::showImage(KonaImage *Ki) {
    qDebug() << "MainWindow: SHOW " << Ki->getId();
    imageViewer->showLoading();

    connect(Ki, SIGNAL(imageDownloaded(KonaImage*,QString)),
            imageViewer, SLOT(setImage(KonaImage*)));

    Ki->DownloadImage();

    if (!imageViewer->isVisible()) {
        imageViewer->show();
    }




    // PRELOADING (not clean but functional)
        QList<KonaPreviewImageView*> kpiv = findChildren<KonaPreviewImageView*>();

        int x;
        for (x=0; x < kpiv.count(); x++) {
            if (x < 1) { // Make sure we don't try to load non existent images

            }
            else if (kpiv.at(x)->getKonaImage()->getId() == Ki->getId()) {
                // Preloading
                int y;
                for (y=0; y < PRELOAD_AMOUNT; y++) { // TODO: Add preload limit to appconfig
                    if (x+1+y < kpiv.count()) {
                        qDebug() << "MainWindow: Will preload image " << kpiv.at(x+1+y)->getKonaImage()->getId();
                        //downloadImage(kpiv.at(x+1+y)->getKonaImage(), false);
                        connect(kpiv.at(x+y)->getKonaImage(), SIGNAL(imageDownloaded(KonaImage*,QString)),
                                kpiv.at(x+1+y)->getKonaImage(), SLOT(DownloadImage()));
                    }
                }
                break;
            }
        }
}

void MainWindow::downloadImage(KonaImage *Ki) {
    qDebug() << "MainWindow: downloadImage " + Ki->getId();
    qDebug() << "MainWindow: downloadImage: THIS FUNCTION IS DEPRECTAED AND WILL BE REMOVED!";
    downloadImage(Ki, true);
}

void MainWindow::downloadImage(KonaImage *Ki, bool overwrite) {
    qDebug() << "DOWNLOAD " << Ki->getId();
    ui->statusBar->showMessage("Downloading image " + QString::number(Ki->getId()) + "...");
    Ki->DownloadImage(overwrite); // TODO: Do we want to have true here?
}

void MainWindow::tagClicked(QString link) {
    QStringList temp = link.split("?");

    if (temp.at(0) == "srcTag") {
        ui->txtSearch->setText(temp.at(1));
        searchPosts(); // TODO: later it needs to support pools!
    }
    else if (temp.at(0) == "addTag") {
        if (ui->txtSearch->text().toLower().indexOf(temp.at(1).toLower()) == -1) {
            ui->txtSearch->setText(ui->txtSearch->text() + " " + temp.at(1));
            searchPosts(); // TODO: support pools
        }
    }
}

void MainWindow::tagsFinished(KonaTags *kt)
{
    QString out;
    for (int x=0; x < kt->getTags().count(); x++) {
        KonaTag *tag = kt->getTags().at(x);
        out.append("<a href='addTag?" + tag->getName() + "'>+</a><a href='srcTag?" + tag->getName() + "'>" + tag->getName() + "</a> <font size=2>(" + QString::number(tag->getCount()) + ")</font><br />");
    }

    ui->lblTags->setText(out);
}

void MainWindow::relatedTagsFinished(KonaRelatedTags *krt) //TODO: Merge with tagsFinished()
{
    QString out;
    for (int x=0; x < krt->getTags().count(); x++) {
        KonaTag *tag = krt->getTags().at(x);
        out.append("<a href='addTag?" + tag->getName() + "'>+</a><a href='srcTag?" + tag->getName() + "'>" + tag->getName() + "</a> <font size=2>(" + QString::number(tag->getCount()) + ")</font><br />");
    }
    ui->lblTags->setText(out);
}

void MainWindow::clearList() {
    QLayoutItem* item;
    while ( ( item = flowLayout->takeAt( 0 ) ) != NULL )
    {
        delete item->widget();
        delete item;
    }
}
