/* This file is part of the KDE project
   Copyright (C) 2011-2013 Jarosław Staniek <staniek@kde.org>

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library 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
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this program; see the file COPYING.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "KexiWelcomeAssistant.h"
#include "KexiRecentProjectsModel.h"
#include "KexiWelcomeStatusBar.h"
#include "KexiPasswordPage.h"
#include "KexiMainWindow.h"
#include <core/kexi.h>
#include <core/KexiRecentProjects.h>
#include <core/kexiprojectdata.h>
#include <core/kexiguimsghandler.h>
#include <core/kexitextmsghandler.h>
#include <kexiutils/utils.h>
#include <kexiutils/KexiAssistantPage.h>
#include <kexiutils/KexiLinkWidget.h>

#include <KDbUtils>
#include <KDbObject>
#include <KDb>

#include <KLocalizedString>

#include <QDebug>
#include <QCheckBox>
#include <QTimer>
#include <QHBoxLayout>

KexiMainWelcomePage::KexiMainWelcomePage(
   KexiWelcomeAssistant* assistant, QWidget* parent)
 : KexiAssistantPage(xi18nc("@title:window", "Welcome to Kexi"),
                  xi18nc("@info", "Select one of the recently used projects to open."),
                  parent)
 , m_assistant(assistant)
{
    QWidget* contents = new QWidget;
    QHBoxLayout* contentsLyr = new QHBoxLayout(contents);

    m_recentProjects = new KexiCategorizedView;
    // do not alter background palette
    QPalette pal(m_recentProjects->palette());
    pal.setColor(QPalette::Disabled, QPalette::Base,
                    pal.color(QPalette::Normal, QPalette::Base));
    m_recentProjects->setPalette(pal);
    contentsLyr->addWidget(m_recentProjects, 1);
    setFocusWidget(m_recentProjects);
    m_recentProjects->setFrameShape(QFrame::NoFrame);
    m_recentProjects->setContentsMargins(0, 0, 0, 0);
    int margin = style()->pixelMetric(QStyle::PM_MenuPanelWidth, 0, 0)
        + KexiUtils::marginHint();
    //not needed in grid:
    m_recentProjects->setSpacing(margin);
    m_recentProjects->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
    if (KexiUtils::activateItemsOnSingleClick(m_recentProjects)) {
        connect(m_recentProjects, SIGNAL(clicked(QModelIndex)), this, SLOT(slotItemClicked(QModelIndex)));
    } else {
        connect(m_recentProjects, SIGNAL(activated(QModelIndex)), this, SLOT(slotItemClicked(QModelIndex)));
    }

    m_statusBar = new KexiWelcomeStatusBar;
    contentsLyr->addWidget(m_statusBar);

    setContents(contents);

    QTimer::singleShot(100, this, SLOT(loadProjects()));
}

void KexiMainWelcomePage::loadProjects()
{
    m_recentProjectsProxyModel = new KexiRecentProjectsProxyModel(m_recentProjects);
    KexiRecentProjectsModel* model = new KexiRecentProjectsModel(*m_assistant->projects(), this);
    m_recentProjectsProxyModel->setSourceModel(model);
    m_recentProjects->setModel(m_recentProjectsProxyModel);
    m_recentProjectsProxyModel->sort(0, Qt::DescendingOrder);
}

void KexiMainWelcomePage::slotItemClicked(const QModelIndex& index)
{
    if (!index.isValid())
        return;
    m_clickedIndex = index;
    QModelIndex sourceIndex = m_recentProjectsProxyModel->mapToSource(index);
    KexiProjectData *pdata = static_cast<KexiProjectData*>(sourceIndex.internalPointer());
    //qDebug() << *pdata;
    if (pdata) {
        m_assistant->openProjectOrShowPasswordPage(pdata);
    }
}

void KexiMainWelcomePage::updateRecentProjects()
{
    m_recentProjects->update();
}

// ----

class Q_DECL_HIDDEN KexiWelcomeAssistant::Private
{
public:
    explicit Private(KexiWelcomeAssistant *qq)
     : q(qq)
    {
    }

    ~Private()
    {
        mainWindow->setRedirection(0);
    }

    KexiMainWelcomePage* mainWelcomePage() {
        return page<KexiMainWelcomePage>(&m_mainWelcomePage, q);
    }
    KexiPasswordPage* passwordPage() {
        return page<KexiPasswordPage>(&m_passwordPage, q);
    }

    template <class C>
    C* page(QPointer<C>* p, KexiWelcomeAssistant *parent = 0) {
        if (p->isNull()) {
            *p = new C(parent);
            q->addPage(*p);
        }
        return *p;
    }

    QPointer<KexiMainWelcomePage> m_mainWelcomePage;
    QPointer<KexiPasswordPage> m_passwordPage;

    QAction* messageWidgetActionNo;
    QAction* messageWidgetActionTryAgain;
    QPointer<KexiContextMessageWidget> messageWidget;

    KexiRecentProjects* projects;
    QPointer<KexiProjectData> projectData;

    KexiMainWindow *mainWindow;

    KexiWelcomeAssistant *q;
};

// ----

KexiWelcomeAssistant::KexiWelcomeAssistant(
    KexiRecentProjects* projects, KexiMainWindow* parent)
 : KexiAssistantWidget(parent)
 , d(new Private(this))
{
    d->mainWindow = parent;
    d->mainWindow->setRedirection(this);
    d->messageWidgetActionNo = 0;
    d->messageWidgetActionTryAgain = 0;
    d->projects = projects;
    setCurrentPage(d->mainWelcomePage());
    setFocusProxy(d->mainWelcomePage());
}

KexiWelcomeAssistant::~KexiWelcomeAssistant()
{
    delete d;
}

void KexiWelcomeAssistant::nextPageRequested(KexiAssistantPage* page)
{
    if (page == d->m_passwordPage) {
        if (d->projectData) {
            d->passwordPage()->updateConnectionData(d->projectData->connectionData());
            emitOpenProject(d->projectData);
        }
    }
    else {
        d->projectData = 0;
    }
}

void KexiWelcomeAssistant::cancelRequested(KexiAssistantPage* page)
{
    Q_UNUSED(page);
    //! @todo
}

KexiRecentProjects* KexiWelcomeAssistant::projects()
{
    return d->projects;
}

void KexiWelcomeAssistant::emitOpenProject(KexiProjectData *data)
{
    bool opened = false;
    emit openProject(*data, projects()->shortcutPath(*data), &opened);
    if (opened) { // update recent projects view
        data->setLastOpened(QDateTime::currentDateTime());
        d->m_mainWelcomePage->updateRecentProjects();
    }
}

void KexiWelcomeAssistant::openProjectOrShowPasswordPage(KexiProjectData *data)
{
    KDbConnectionData *cdata = data->connectionData();
    if (cdata) {
        if (cdata->isPasswordNeeded()) {
            d->projectData = data;
            d->passwordPage()->setConnectionData(*cdata);
            d->passwordPage()->showDatabaseName(true);
            d->passwordPage()->setDatabaseNameReadOnly(true);
            d->passwordPage()->setDatabaseName(data->databaseName());
            setCurrentPage(d->passwordPage());
            return;
        }
        else {
            d->projectData = 0;
            emitOpenProject(data);
        }
    }

}

void KexiWelcomeAssistant::tryAgainActionTriggered()
{
    if (currentPage() == d->mainWelcomePage()) {
        d->mainWelcomePage()->slotItemClicked(d->mainWelcomePage()->clickedItem());
    } else if (currentPage() == d->passwordPage()) {
        currentPage()->next();
    }
}

void KexiWelcomeAssistant::cancelActionTriggered()
{
    if (currentPage() == d->mainWelcomePage()) {
        d->mainWelcomePage()->recentProjectsView()->clearSelection();
    } else if (currentPage() == d->passwordPage()) {
        d->passwordPage()->focusWidget()->setFocus();
    }
}

const QWidget* KexiWelcomeAssistant::calloutWidget() const
{
    if (currentPage() == d->mainWelcomePage()) {
        return d->mainWelcomePage()->recentProjectsView();
    } else if (currentPage() == d->passwordPage()) {
        return currentPage()->nextButton();
    }
    return 0;
}

QPoint KexiWelcomeAssistant::calloutPointerPosition() const
{
    if (currentPage() == d->mainWelcomePage()) {
        const QRect clickedItemRect
            = d->mainWelcomePage()->recentProjectsView()->visualRect(
                    d->mainWelcomePage()->clickedItem());
        return QPoint(clickedItemRect.center().x(), clickedItemRect.bottom());
    } else if (currentPage() == d->passwordPage()) {
        return KexiAssistantMessageHandler::calloutPointerPosition();
    }
    return QPoint();
}

KMessageWidget::CalloutPointerDirection KexiWelcomeAssistant::calloutPointerDirection() const
{
    if (currentPage() == d->mainWelcomePage()) {
        return KMessageWidget::Up;
    } else {
        return KexiAssistantMessageHandler::calloutPointerDirection();
    }
}
