// Distributed under the Boost Software License, Version 1.0.
//    (See accompanying file LICENSE_1_0.txt or copy at
//          http://www.boost.org/LICENSE_1_0.txt)

#include "mapview.h"

#include <QtCore/QTime>
#include <QtCore/QDebug>
#include <QtCore/QCoreApplication>
#include <QtDeclarative/qdeclarative.h>
#include <QtGui/QGraphicsScene>
#include <QtGui/QGraphicsSceneMouseEvent>
#include <QtGui/QPainter>
#include <QtDeclarative/private/qdeclarativeflickable_p.h>
#include <qmath.h>

MapView::MapView(QDeclarativeItem *parent)
    : QDeclarativeItem(parent)
    , m_pixmap(QCoreApplication::applicationDirPath() + "/qml/graphics.png")
    , m_model(0)
    , m_blockSize(m_blockSize)
{
    if (m_pixmap.isNull())
        qFatal("Could not load qml/graphics.png!");

    setFlag(QGraphicsItem::ItemHasNoContents, false);
}

void MapView::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
{
    if (!m_model)
        return;

    int startX = 0;
    int startY = 0;
    int endX = m_model->columnCount();
    int endY = m_model->rowCount();

    if (parentItem()) {
        QDeclarativeFlickable *flickable = qobject_cast<QDeclarativeFlickable *>(parentItem()->parentItem());
        if (flickable) {
            startX = flickable->contentX() / m_blockSize;
            startY = flickable->contentY() / m_blockSize;
            endX = startX + flickable->width() / m_blockSize + 2;
            endY = startY + flickable->height() / m_blockSize + 2;
        }
    }

    for (int x = startX; x < endX; ++x) {
        for (int y = startY; y < endY; ++y) {
            int sx = 0;
            int sy = 0;
            const int type = m_model->data(m_model->index(y, x)).toInt();
            if (type > 0) {
                sx = 12 * ((type-1)%12);
                sy = 12 * qFloor((type-1)/12);
            }
            painter->drawPixmap(x*m_blockSize, y*m_blockSize, m_blockSize, m_blockSize, m_pixmap, sx, sy, 12, 12);
        }
    }
}

QVariant MapView::model() const
{
    return m_modelVariant;
}

void MapView::setModel(QVariant m)
{
    QObject *object = qvariant_cast<QObject *>(m);
    QAbstractItemModel *abstractItemModel = qobject_cast<QAbstractItemModel *>(object);
    if (abstractItemModel && abstractItemModel != m_model) {
        if (m_model) {
            disconnect(m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(triggerUpdate()));
            disconnect(m_model, SIGNAL(modelReset()), this, SLOT(updateImplicitSize()));
        }
        connect(abstractItemModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(triggerUpdate()));
        connect(abstractItemModel, SIGNAL(modelReset()), this, SLOT(updateImplicitSize()));
        m_modelVariant = m;
        m_model = abstractItemModel;
        updateImplicitSize();
        emit modelChanged();
    }
}

int MapView::blockSize() const
{
    return m_blockSize;
}

void MapView::setBlockSize(int b)
{
    if (b != m_blockSize) {
        m_blockSize = b;
        updateImplicitSize();
        emit blockSizeChanged();
    }
}

void MapView::triggerUpdate()
{
    update();
}

void MapView::updateImplicitSize()
{
    setImplicitWidth(m_blockSize*m_model->columnCount());
    setImplicitHeight(m_blockSize*m_model->rowCount());
    update();
}

QML_DECLARE_TYPE(MapView);
