/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Copyright (C) 2014 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtLocation module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPLv3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or later as published by the Free
** Software Foundation and appearing in the file LICENSE.GPL included in
** the packaging of this file. Please review the following information to
** ensure the GNU General Public License version 2.0 requirements will be
** met: http://www.gnu.org/licenses/gpl-2.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qgeotiledmapscene_p.h"
#include "qgeotiledmapscene_p_p.h"
#include "qgeocameradata_p.h"
#include "qabstractgeotilecache_p.h"
#include "qgeotilespec_p.h"
#include <QtPositioning/private/qdoublevector3d_p.h>
#include <QtPositioning/private/qwebmercator_p.h>
#include <QtCore/private/qobject_p.h>
#include <QtQuick/QQuickWindow>
#include <QtGui/QVector3D>
#include <cmath>
#include <QtPositioning/private/qlocationutils_p.h>
#include <QtPositioning/private/qdoublematrix4x4_p.h>
#include <QtPositioning/private/qwebmercator_p.h>

static QVector3D toVector3D(const QDoubleVector3D& in)
{
    return QVector3D(in.x(), in.y(), in.z());
}

QT_BEGIN_NAMESPACE

QGeoTiledMapScene::QGeoTiledMapScene(QObject *parent)
    : QObject(*new QGeoTiledMapScenePrivate(),parent)
{
}

QGeoTiledMapScene::~QGeoTiledMapScene()
{
}

void QGeoTiledMapScene::setScreenSize(const QSize &size)
{
    Q_D(QGeoTiledMapScene);
    d->m_screenSize = size;
}

void QGeoTiledMapScene::updateSceneParameters()
{
    Q_D(QGeoTiledMapScene);
    d->m_intZoomLevel = static_cast<int>(std::floor(d->m_cameraData.zoomLevel()));
    const float delta = d->m_cameraData.zoomLevel() - d->m_intZoomLevel;
    d->m_linearScaling = qAbs(delta) > 0.05 || d->isTiltedOrRotated();
    d->m_sideLength = 1 << d->m_intZoomLevel;
    d->m_mapEdgeSize = std::pow(2.0, d->m_cameraData.zoomLevel()) * d->m_tileSize;
}

void QGeoTiledMapScene::setTileSize(int tileSize)
{
    Q_D(QGeoTiledMapScene);
    if (d->m_tileSize == tileSize)
        return;

    d->m_tileSize = tileSize;
    updateSceneParameters();
}

void QGeoTiledMapScene::setCameraData(const QGeoCameraData &cameraData)
{
    Q_D(QGeoTiledMapScene);
    d->m_cameraData = cameraData;
    updateSceneParameters();
}

void QGeoTiledMapScene::setVisibleArea(const QRectF &visibleArea)
{
    Q_D(QGeoTiledMapScene);
    if (d->m_visibleArea == visibleArea)
        return;
    d->m_visibleArea = visibleArea;
    updateSceneParameters();
}

void QGeoTiledMapScene::setVisibleTiles(const QSet<QGeoTileSpec> &tiles)
{
    Q_D(QGeoTiledMapScene);
    d->setVisibleTiles(tiles);
}

const QSet<QGeoTileSpec> &QGeoTiledMapScene::visibleTiles() const
{
    Q_D(const QGeoTiledMapScene);
    return d->m_visibleTiles;
}

void QGeoTiledMapScene::addTile(const QGeoTileSpec &spec, QSharedPointer<QGeoTileTexture> texture)
{
    Q_D(QGeoTiledMapScene);
    d->addTile(spec, texture);
}

QSet<QGeoTileSpec> QGeoTiledMapScene::texturedTiles()
{
    Q_D(QGeoTiledMapScene);
    QSet<QGeoTileSpec> textured;
    for (auto it = d->m_textures.cbegin(); it != d->m_textures.cend(); ++it)
        textured += it.value()->spec;

    return textured;
}

void QGeoTiledMapScene::clearTexturedTiles()
{
    Q_D(QGeoTiledMapScene);
    d->m_textures.clear();
    d->m_dropTextures = true;
}

QGeoTiledMapScenePrivate::QGeoTiledMapScenePrivate()
    : QObjectPrivate(),
      m_tileSize(0),
#ifdef QT_LOCATION_DEBUG
      m_scaleFactor(1.0),
#else
      m_scaleFactor(10.0),
#endif
      m_intZoomLevel(0),
      m_sideLength(0),
      m_minTileX(-1),
      m_minTileY(-1),
      m_maxTileX(-1),
      m_maxTileY(-1),
      m_tileXWrapsBelow(0),
      m_linearScaling(false),
      m_dropTextures(false)
{
}

QGeoTiledMapScenePrivate::~QGeoTiledMapScenePrivate()
{
}

bool QGeoTiledMapScenePrivate::buildGeometry(const QGeoTileSpec &spec, QSGImageNode *imageNode, bool &overzooming)
{
    overzooming = false;
    int x = spec.x();

    if (x < m_tileXWrapsBelow)
        x += m_sideLength;

    if ((x < m_minTileX)
            || (m_maxTileX < x)
            || (spec.y() < m_minTileY)
            || (m_maxTileY < spec.y())
            || (spec.zoom() != m_intZoomLevel)) {
        return false;
    }

    double edge = m_scaleFactor * m_tileSize;

    double x1 = (x - m_minTileX);
    double x2 = x1 + 1.0;

    double y1 = (m_minTileY - spec.y());
    double y2 = y1 - 1.0;

    x1 *= edge;
    x2 *= edge;
    y1 *= edge;
    y2 *= edge;

    imageNode->setRect(QRectF(QPointF(x1, y2), QPointF(x2, y1)));
    imageNode->setTextureCoordinatesTransform(QSGImageNode::MirrorVertically);

    // Calculate the texture mapping, in case we are magnifying some lower ZL tile
    const auto it = m_textures.find(spec); // This should be always found, but apparently sometimes it isn't, possibly due to memory shortage
    if (it != m_textures.end()) {
        if (it.value()->spec.zoom() < spec.zoom()) {
            // Currently only using lower ZL tiles for the overzoom.
            const int tilesPerTexture = 1 << (spec.zoom() - it.value()->spec.zoom());
            const int mappedSize = imageNode->texture()->textureSize().width() / tilesPerTexture;
            const int x = (spec.x() % tilesPerTexture) * mappedSize;
            const int y = (spec.y() % tilesPerTexture) * mappedSize;
            imageNode->setSourceRect(QRectF(x, y, mappedSize, mappedSize));
            overzooming = true;
        } else {
            imageNode->setSourceRect(QRectF(QPointF(0,0), imageNode->texture()->textureSize()));
        }
    } else {
        qWarning() << "!! buildGeometry: tileSpec not present in m_textures !!";
        imageNode->setSourceRect(QRectF(QPointF(0,0), imageNode->texture()->textureSize()));
    }

    return true;
}

void QGeoTiledMapScenePrivate::addTile(const QGeoTileSpec &spec, QSharedPointer<QGeoTileTexture> texture)
{
    if (!m_visibleTiles.contains(spec)) // Don't add the geometry if it isn't visible
        return;

    if (m_textures.contains(spec))
        m_updatedTextures.append(spec);
    m_textures.insert(spec, texture);
}

void QGeoTiledMapScenePrivate::setVisibleTiles(const QSet<QGeoTileSpec> &visibleTiles)
{
    // work out the tile bounds for the new scene
    updateTileBounds(visibleTiles);

    // set up the gl camera for the new scene
    setupCamera();

    QSet<QGeoTileSpec> toRemove = m_visibleTiles - visibleTiles;
    if (!toRemove.isEmpty())
        removeTiles(toRemove);

    m_visibleTiles = visibleTiles;
}

void QGeoTiledMapScenePrivate::removeTiles(const QSet<QGeoTileSpec> &oldTiles)
{
    typedef QSet<QGeoTileSpec>::const_iterator iter;
    iter i = oldTiles.constBegin();
    iter end = oldTiles.constEnd();

    for (; i != end; ++i) {
        QGeoTileSpec tile = *i;
        m_textures.remove(tile);
    }
}

void QGeoTiledMapScenePrivate::updateTileBounds(const QSet<QGeoTileSpec> &tiles)
{
    if (tiles.isEmpty()) {
        m_minTileX = -1;
        m_minTileY = -1;
        m_maxTileX = -1;
        m_maxTileY = -1;
        return;
    }

    typedef QSet<QGeoTileSpec>::const_iterator iter;
    iter i = tiles.constBegin();
    iter end = tiles.constEnd();

    // determine whether the set of map tiles crosses the dateline.
    // A gap in the tiles indicates dateline crossing
    bool hasFarLeft = false;
    bool hasFarRight = false;
    bool hasMidLeft = false;
    bool hasMidRight = false;

    for (; i != end; ++i) {
        if ((*i).zoom() != m_intZoomLevel)
            continue;
        int x = (*i).x();
        if (x == 0)
            hasFarLeft = true;
        else if (x == (m_sideLength - 1))
            hasFarRight = true;
        else if (x == ((m_sideLength / 2) - 1)) {
            hasMidLeft = true;
        } else if (x == (m_sideLength / 2)) {
            hasMidRight = true;
        }
    }

    // if dateline crossing is detected we wrap all x pos of tiles
    // that are in the left half of the map.
    m_tileXWrapsBelow = 0;

    if (hasFarLeft && hasFarRight) {
        if (!hasMidRight) {
            m_tileXWrapsBelow = m_sideLength / 2;
        } else if (!hasMidLeft) {
            m_tileXWrapsBelow = (m_sideLength / 2) - 1;
        }
    }

    // finally, determine the min and max bounds
    i = tiles.constBegin();

    QGeoTileSpec tile = *i;

    int x = tile.x();
    if (tile.x() < m_tileXWrapsBelow)
        x += m_sideLength;

    m_minTileX = x;
    m_maxTileX = x;
    m_minTileY = tile.y();
    m_maxTileY = tile.y();

    ++i;

    for (; i != end; ++i) {
        tile = *i;
        if (tile.zoom() != m_intZoomLevel)
            continue;

        int x = tile.x();
        if (tile.x() < m_tileXWrapsBelow)
            x += m_sideLength;

        m_minTileX = qMin(m_minTileX, x);
        m_maxTileX = qMax(m_maxTileX, x);
        m_minTileY = qMin(m_minTileY, tile.y());
        m_maxTileY = qMax(m_maxTileY, tile.y());
    }
}

void QGeoTiledMapScenePrivate::setupCamera()
{
    // NOTE: The following instruction is correct only because WebMercator is a square projection!
    double f = m_screenSize.height();

    // Using fraction of zoom level, z varies between [ m_tileSize , 2 * m_tileSize [
    double z = std::pow(2.0, m_cameraData.zoomLevel() - m_intZoomLevel) * m_tileSize;

    // calculate altitude that allows the visible map tiles
    // to fit in the screen correctly (note that a larger f will cause
    // the camera be higher, resulting in gray areas displayed around
    // the tiles)
    double altitude = f / (2.0 * z);

    // calculate center
    double edge = m_scaleFactor * m_tileSize;

    // first calculate the camera center in map space in the range of 0 <-> sideLength (2^z)
    QDoubleVector2D camCenterMercator = QWebMercator::coordToMercator(m_cameraData.center());
    QDoubleVector3D center = (m_sideLength * camCenterMercator);

    // wrap the center if necessary (due to dateline crossing)
    if (center.x() < m_tileXWrapsBelow)
        center.setX(center.x() + 1.0 * m_sideLength);

    // work out where the camera center is w.r.t minimum tile bounds
    center.setX(center.x() - 1.0 * m_minTileX);
    center.setY(1.0 * m_minTileY - center.y());

    // apply necessary scaling to the camera center
    center *= edge;

    // calculate eye
    double apertureSize = 1.0;
    if (m_cameraData.fieldOfView() != 90.0) //aperture(90 / 2) = 1
        apertureSize = tan(QLocationUtils::radians(m_cameraData.fieldOfView()) * 0.5);
    QDoubleVector3D eye = center;
    eye.setZ(altitude * edge / apertureSize);

    // calculate up

    QDoubleVector3D view = eye - center;
    QDoubleVector3D side = QDoubleVector3D::normal(view, QDoubleVector3D(0.0, 1.0, 0.0));
    QDoubleVector3D up = QDoubleVector3D::normal(side, view);

    // old bearing, tilt and roll code.
    // Now using double matrices until distilling the transformation to QMatrix4x4
    QDoubleMatrix4x4 mBearing;
    // -1.0 * bearing removed, now map north goes in the bearing direction
    mBearing.rotate(-1.0 * m_cameraData.bearing(), view);
    up = mBearing * up;

    QDoubleVector3D side2 = QDoubleVector3D::normal(up, view);
    if (m_cameraData.tilt() > 0.01) {
        QDoubleMatrix4x4 mTilt;
        mTilt.rotate(m_cameraData.tilt(), side2);
        eye = mTilt * view + center;
    }

    view = eye - center;
    view.normalize();
    side = QDoubleVector3D::normal(view, QDoubleVector3D(0.0, 1.0, 0.0));
    up = QDoubleVector3D::normal(view, side2);

    //    QMatrix4x4 mRoll;
    //    mRoll.rotate(camera.roll(), view);
    //    up = mRoll * up;

    // near plane and far plane

    double nearPlane = 1.0;
    // Clip plane. Used to be (altitude + 1.0) * edge. This does not affect the perspective. minimum value would be > 0.0
    // Since, for some reasons possibly related to how QSG works, this clipping plane is unable to clip part of tiles,
    // Instead of farPlane =  (altitude + m_cameraData.clipDistance()) * edge , we use a fixed large clipDistance, and
    // leave the clipping only in QGeoCameraTiles::createFrustum
    double farPlane =  (altitude + 10000.0) * edge;

    m_cameraUp = up;
    m_cameraCenter = center;
    m_cameraEye = eye;

    double aspectRatio = 1.0 * m_screenSize.width() / m_screenSize.height();
    float halfWidth = 1 * apertureSize;
    float halfHeight = 1 * apertureSize;
    halfWidth *= aspectRatio;

//    m_projectionMatrix.setToIdentity();
//    m_projectionMatrix.frustum(-halfWidth, halfWidth, -halfHeight, halfHeight, nearPlane, farPlane);

    QRectF va = m_visibleArea;
    if (va.isNull())
        va = QRectF(0, 0, m_screenSize.width(), m_screenSize.height());

    QRectF screen = QRectF(QPointF(0,0),m_screenSize);
    QPointF vaCenter = va.center();

    QPointF screenCenter = screen.center();
    QPointF diff = screenCenter - vaCenter;
    float xdiffpct = diff.x() / m_screenSize.width();
    float ydiffpct = -(diff.y() / m_screenSize.height());

    m_projectionMatrix.setToIdentity();
    float l = -halfWidth + (2 * halfWidth) * xdiffpct;
    float r =  halfWidth + (2 * halfWidth) * xdiffpct;
    float t =  halfHeight + (2 * halfHeight) * ydiffpct;
    float b = -halfHeight + (2 * halfHeight) * ydiffpct;

    m_projectionMatrix.frustum(l,
                               r,
                               b,
                               t,
                               nearPlane, farPlane);
}

static bool qgeotiledmapscene_isTileInViewport_Straight(const QRectF &tileRect, const QMatrix4x4 &matrix)
{
    const QRectF boundingRect = QRectF(matrix * tileRect.topLeft(), matrix * tileRect.bottomRight());
    return QRectF(-1, -1, 2, 2).intersects(boundingRect);
}

static bool qgeotiledmapscene_isTileInViewport_rotationTilt(const QRectF &tileRect, const QMatrix4x4 &matrix)
{
    // Transformed corners
    const QPointF tlt = matrix * tileRect.topLeft();
    const QPointF trt = matrix * tileRect.topRight();
    const QPointF blt = matrix * tileRect.bottomLeft();
    const QPointF brt = matrix * tileRect.bottomRight();

    const QRectF boundingRect = QRectF(QPointF(qMin(qMin(qMin(tlt.x(), trt.x()), blt.x()), brt.x())
                                              ,qMax(qMax(qMax(tlt.y(), trt.y()), blt.y()), brt.y()))
                                      ,QPointF(qMax(qMax(qMax(tlt.x(), trt.x()), blt.x()), brt.x())
                                              ,qMin(qMin(qMin(tlt.y(), trt.y()), blt.y()), brt.y()))
                                       );
    return QRectF(-1, -1, 2, 2).intersects(boundingRect);
}

static bool qgeotiledmapscene_isTileInViewport(const QRectF &tileRect, const QMatrix4x4 &matrix, const bool straight)
{
    if (straight)
        return qgeotiledmapscene_isTileInViewport_Straight(tileRect, matrix);
    return qgeotiledmapscene_isTileInViewport_rotationTilt(tileRect, matrix);
}

void QGeoTiledMapRootNode::updateTiles(QGeoTiledMapTileContainerNode *root,
                                       QGeoTiledMapScenePrivate *d,
                                       double camAdjust,
                                       QQuickWindow *window,
                                       bool ogl)
{
    // Set up the matrix...
    QDoubleVector3D eye = d->m_cameraEye;
    eye.setX(eye.x() + camAdjust);
    QDoubleVector3D center = d->m_cameraCenter;
    center.setX(center.x() + camAdjust);
    QMatrix4x4 cameraMatrix;
    cameraMatrix.lookAt(toVector3D(eye), toVector3D(center), toVector3D(d->m_cameraUp));
    root->setMatrix(d->m_projectionMatrix * cameraMatrix);

    QSet<QGeoTileSpec> tilesInSG;
    for (auto it = root->tiles.cbegin(), end = root->tiles.cend(); it != end; ++it)
        tilesInSG.insert(it.key());
    const QSet<QGeoTileSpec> toRemove = tilesInSG - d->m_visibleTiles;
    const QSet<QGeoTileSpec> toAdd = d->m_visibleTiles - tilesInSG;

    for (const QGeoTileSpec &s : toRemove)
        delete root->tiles.take(s);
    bool straight = !d->isTiltedOrRotated();
    bool overzooming;
    qreal pixelRatio = window->effectiveDevicePixelRatio();
#ifdef QT_LOCATION_DEBUG
    QList<QGeoTileSpec> droppedTiles;
#endif
    for (QHash<QGeoTileSpec, QSGImageNode *>::iterator it = root->tiles.begin();
         it != root->tiles.end(); ) {
        QSGImageNode *node = it.value();
        bool ok = d->buildGeometry(it.key(), node, overzooming)
                && qgeotiledmapscene_isTileInViewport(node->rect(), root->matrix(), straight);

        QSGNode::DirtyState dirtyBits = 0;

        if (!ok) {
#ifdef QT_LOCATION_DEBUG
            droppedTiles.append(it.key());
#endif
            it = root->tiles.erase(it);
            delete node;
        } else {
            if (isTextureLinear != d->m_linearScaling) {
                if (node->texture()->textureSize().width() > d->m_tileSize * pixelRatio) {
                    node->setFiltering(QSGTexture::Linear); // With mipmapping QSGTexture::Nearest generates artifacts
                    node->setMipmapFiltering(QSGTexture::Linear);
                } else {
                    node->setFiltering((d->m_linearScaling || overzooming) ? QSGTexture::Linear : QSGTexture::Nearest);
                }
#if QT_CONFIG(opengl)
                if (ogl)
                    static_cast<QSGDefaultImageNode *>(node)->setAnisotropyLevel(QSGTexture::Anisotropy16x);
#else
    Q_UNUSED(ogl);
#endif
                dirtyBits |= QSGNode::DirtyMaterial;
            }
            if (dirtyBits != 0)
                node->markDirty(dirtyBits);
            it++;
        }
    }

    for (const QGeoTileSpec &s : toAdd) {
        QGeoTileTexture *tileTexture = d->m_textures.value(s).data();
        if (!tileTexture || tileTexture->image.isNull()) {
#ifdef QT_LOCATION_DEBUG
            droppedTiles.append(s);
#endif
            continue;
        }
        QSGImageNode *tileNode = window->createImageNode();
        // note: setTexture will update coordinates so do it here, before we buildGeometry
        tileNode->setTexture(textures.value(s));
        if (d->buildGeometry(s, tileNode, overzooming)
                && qgeotiledmapscene_isTileInViewport(tileNode->rect(), root->matrix(), straight)) {
            if (tileNode->texture()->textureSize().width() > d->m_tileSize * pixelRatio) {
                tileNode->setFiltering(QSGTexture::Linear); // with mipmapping QSGTexture::Nearest generates artifacts
                tileNode->setMipmapFiltering(QSGTexture::Linear);
            } else {
                tileNode->setFiltering((d->m_linearScaling || overzooming) ? QSGTexture::Linear : QSGTexture::Nearest);
            }
#if QT_CONFIG(opengl)
            if (ogl)
                static_cast<QSGDefaultImageNode *>(tileNode)->setAnisotropyLevel(QSGTexture::Anisotropy16x);
#endif
            root->addChild(s, tileNode);
        } else {
#ifdef QT_LOCATION_DEBUG
            droppedTiles.append(s);
#endif
            delete tileNode;
        }
    }

#ifdef QT_LOCATION_DEBUG
    m_droppedTiles[camAdjust] = droppedTiles;
#endif
}

QSGNode *QGeoTiledMapScene::updateSceneGraph(QSGNode *oldNode, QQuickWindow *window)
{
    Q_D(QGeoTiledMapScene);
    float w = d->m_screenSize.width();
    float h = d->m_screenSize.height();
    if (w <= 0 || h <= 0) {
        delete oldNode;
        return 0;
    }

    bool isOpenGL = (window->rendererInterface()->graphicsApi() == QSGRendererInterface::OpenGL);
    QGeoTiledMapRootNode *mapRoot = static_cast<QGeoTiledMapRootNode *>(oldNode);
    if (!mapRoot)
        mapRoot = new QGeoTiledMapRootNode();

#ifdef QT_LOCATION_DEBUG
    mapRoot->m_droppedTiles.clear();
    d->m_mapRoot = mapRoot;
#endif

    // Setting clip rect to fullscreen, as now the map can never be smaller than the viewport.
    mapRoot->setClipRect(QRect(0, 0, w, h));

    QMatrix4x4 itemSpaceMatrix;
    itemSpaceMatrix.scale(w / 2, h / 2);
    itemSpaceMatrix.translate(1, 1);
    itemSpaceMatrix.scale(1, -1);
    mapRoot->root->setMatrix(itemSpaceMatrix);

    if (d->m_dropTextures) {
        for (const QGeoTileSpec &s : mapRoot->tiles->tiles.keys())
            delete mapRoot->tiles->tiles.take(s);
        for (const QGeoTileSpec &s : mapRoot->wrapLeft->tiles.keys())
            delete mapRoot->wrapLeft->tiles.take(s);
        for (const QGeoTileSpec &s : mapRoot->wrapRight->tiles.keys())
            delete mapRoot->wrapRight->tiles.take(s);
        for (const QGeoTileSpec &spec : mapRoot->textures.keys())
            mapRoot->textures.take(spec)->deleteLater();
        d->m_dropTextures = false;
    }

    // Evicting loZL tiles temporarily used in place of hiZL ones
    if (d->m_updatedTextures.size()) {
        const QVector<QGeoTileSpec> &toRemove = d->m_updatedTextures;
        for (const QGeoTileSpec &s : toRemove) {
            if (mapRoot->tiles->tiles.contains(s))
                delete mapRoot->tiles->tiles.take(s);

            if (mapRoot->wrapLeft->tiles.contains(s))
                delete mapRoot->wrapLeft->tiles.take(s);

            if (mapRoot->wrapRight->tiles.contains(s))
                delete mapRoot->wrapRight->tiles.take(s);

            if (mapRoot->textures.contains(s))
                mapRoot->textures.take(s)->deleteLater();
        }
        d->m_updatedTextures.clear();
    }

    QSet<QGeoTileSpec> textures;
    for (auto it = mapRoot->textures.cbegin(), end = mapRoot->textures.cend(); it != end; ++it)
        textures.insert(it.key());
    const QSet<QGeoTileSpec> toRemove = textures - d->m_visibleTiles;
    const QSet<QGeoTileSpec> toAdd = d->m_visibleTiles - textures;

    for (const QGeoTileSpec &spec : toRemove)
        mapRoot->textures.take(spec)->deleteLater();
    for (const QGeoTileSpec &spec : toAdd) {
        QGeoTileTexture *tileTexture = d->m_textures.value(spec).data();
        if (!tileTexture || tileTexture->image.isNull())
            continue;
        mapRoot->textures.insert(spec, window->createTextureFromImage(tileTexture->image));
    }

    double sideLength = d->m_scaleFactor * d->m_tileSize * d->m_sideLength;
#ifdef QT_LOCATION_DEBUG
    d->m_sideLengthPixel = sideLength;
#endif
    mapRoot->updateTiles(mapRoot->tiles, d, 0, window, isOpenGL);
    mapRoot->updateTiles(mapRoot->wrapLeft, d, +sideLength, window, isOpenGL);
    mapRoot->updateTiles(mapRoot->wrapRight, d, -sideLength, window, isOpenGL);

    mapRoot->isTextureLinear = d->m_linearScaling;

    return mapRoot;
}

QT_END_NAMESPACE
