/***************************************************************************
 *   Copyright (C) 2004-2009 by Pere Constans
 *   constans@molspaces.com
 *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
 *   See the LICENSE file that comes with this distribution.
 ***************************************************************************/
#include "c2bCiterView.h"

#include <QHeaderView>
#include <QKeyEvent>


c2bCiterView::c2bCiterView(QWidget* parentw) : QTableView(parentw)
{
    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    setShowGrid(false);
    setTabKeyNavigation(true);
    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);

    horizontalHeader()->setResizeMode(QHeaderView::Fixed);
    horizontalHeader()->setVisible(false);
    verticalHeader()->setDefaultSectionSize(fontMetrics().height() + 5);
    verticalHeader()->setResizeMode(QHeaderView::Fixed);
    verticalHeader()->setVisible(false);

    _modelP = 0;
    _filter_mode = false;
}

c2bCiterView::~c2bCiterView()
{}


void c2bCiterView::setModel(QAbstractItemModel* citations)
{
    if (_modelP != citations)
    {
        _modelP = static_cast<c2bCiterModel*>(citations);
        QTableView::setModel(_modelP);
    }
    setCurrentIndex(_modelP->index(0, 0));
    updateViewport();
}

void c2bCiterView::resizeEvent(QResizeEvent* qevent)
{
    updateViewport();
    QTableView::resizeEvent(qevent);
}

void c2bCiterView::keyPressEvent(QKeyEvent* qevent)
{
    if (_filter_mode)
    {
        switch (qevent->key())
        {
        case Qt::Key_Down:
        case Qt::Key_Enter:
        case Qt::Key_Escape:
        case Qt::Key_Return:
        case Qt::Key_Up:
            _filter_mode = false;
        }
        qevent->ignore();
        return;
    }
    if (qevent->modifiers() & Qt::ShiftModifier)
    {
        if (!qevent->text().isEmpty())
            QTableView::keyboardSearch(qevent->text());
        qevent->accept();
        return;
    }
    switch (qevent->key())
    {
        // Filter mode
    case Qt::Key_F:
        _filter_mode = true;
        qevent->ignore();
        return;
        // Actions
    case Qt::Key_C:
    case Qt::Key_E:
    case Qt::Key_O:
    case Qt::Key_S:
    case Qt::Key_U:
        qevent->ignore();
        return;
    case Qt::Key_Delete:
        _modelP->clearSelection();
        qevent->accept();
        return;
        // Formats
    case Qt::Key_A:
        updateFormat(c2bCiterModel::AJYT);
        qevent->accept();
        return;
    case Qt::Key_J:
        updateFormat(c2bCiterModel::JYA);
        qevent->accept();
        return;
    case Qt::Key_T:
        updateFormat(c2bCiterModel::T);
        qevent->accept();
        return;
    case Qt::Key_Y:
        updateFormat(c2bCiterModel::YAJT);
        qevent->accept();
        return;
        // Navigation
    case Qt::Key_Tab:
    {
        QKeyEvent ke(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier);
        QTableView::keyPressEvent(&ke);
        qevent->accept();
        return;
    }
    case Qt::Key_Backspace:
    {
        QKeyEvent ke(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier);
        QTableView::keyPressEvent(&ke);
        qevent->accept();
        return;
    }
    case Qt::Key_Home:
    {
        QKeyEvent ke(QEvent::KeyPress, Qt::Key_Home, Qt::ControlModifier);
        QTableView::keyPressEvent(&ke);
        qevent->accept();
        return;
    }
    case Qt::Key_End:
    {
        QKeyEvent ke(QEvent::KeyPress, Qt::Key_End, Qt::ControlModifier);
        QTableView::keyPressEvent(&ke);
        qevent->accept();
        return;
    }
    case Qt::Key_Space:
    {
        QKeyEvent ke(QEvent::KeyPress, Qt::Key_PageDown, Qt::NoModifier);
        QTableView::keyPressEvent(&ke);
        qevent->accept();
        return;
    }
    case Qt::Key_Enter:
    case Qt::Key_Return:
    {
        QTableView::keyPressEvent(qevent);
        QKeyEvent ke(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier);
        QTableView::keyPressEvent(&ke);
        qevent->accept();
        return;
    }
    default:
        QTableView::keyPressEvent(qevent);
        qevent->ignore();
    }
}

void c2bCiterView::keyboardSearch(const QString& /* search */)
{}

void c2bCiterView::updateFormat(const c2bCiterModel::Format& format)
{
    if (!_modelP)
        return;
    QModelIndex i = currentIndex();
    _modelP->updateFormat(format, &i);
    updateViewport();
    updateCurrentIndex(i);
}

void c2bCiterView::updateCurrentIndex(const QModelIndex& i)
{
    setCurrentIndex(i);
    scrollTo(i, PositionAtCenter);
}

void c2bCiterView::updateViewport()
{
    if (!_modelP)
        return;
    const int nc(_modelP->columnCount());
    if (nc < 1)
        return;
    const int vp_w(viewport()->size().width());
    if (nc == 1)
    {
        setColumnWidth(0, vp_w);
        return;
    }
    QList<int> w = _modelP->sizeHintForColumns();
    const int char_w(fontMetrics().width(QLatin1Char('N')));
    for (int i = 0; i < nc; ++i)
        w[i] *= char_w;
    int required_w(w.at(0));
    if (required_w >= vp_w)
    {
        setColumnWidth(0, vp_w);
        for (int i = 1; i < nc; ++i)
            setColumnWidth(i, 0);
        return;
    }
    for (int i = 1; i < nc; ++i)
        required_w += w.at(i);
    if (required_w > vp_w)
    {
        int available_w(vp_w - w.at(0));
        int div[] = {0, 0, 0, 0};
        while (available_w > 0)
            for (int i = 1; i < nc; ++i)
                if (div[i] < w.at(i))
                {
                    div[i] += 1;
                    --available_w;
                }
        for (int i = 1; i < nc; ++i)
            w[i] = div[i];
    }
    else
        w[nc-1] += vp_w - required_w;
    for (int i = 0; i < nc; ++i)
        setColumnWidth(i, w.at(i));
}
