/***************************************************************************
  qgsterraingenerator.h
  --------------------------------------
  Date                 : August 2024
  Copyright            : (C) 2024 by David Koňařík
  Email                : dvdkon at konarici dot cz
 ***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#pragma once

#include "qgschunknode.h"
#include "qgscoordinatetransform.h"
#include "qgsmaplayerref.h"
#include "qgsterrainentity.h"
#include "qgsrectangle.h"
#include "qgsterraingenerator.h"
#include "qgsquantizedmeshdataprovider.h"
#include "qgstiledsceneindex.h"
#include "qgstiledscenelayer.h"
#include "qgstiles.h"

#define SIP_NO_FILE

/**
 * \ingroup 3d
 * \brief Terrain generator using a Quantized Mesh tile layer
 * \since QGIS 3.40
 */
class _3D_EXPORT QgsQuantizedMeshTerrainGenerator : public QgsTerrainGenerator
{
    Q_OBJECT
  public:
    QgsQuantizedMeshTerrainGenerator() { mIsValid = false; }

    virtual void setTerrain( QgsTerrainEntity *t ) override;
    virtual QgsTerrainGenerator *clone() const override SIP_FACTORY;
    virtual QgsTerrainGenerator::Type type() const override;
    virtual void setExtent( const QgsRectangle &extent ) override;
    virtual QgsRectangle rootChunkExtent() const override;
    virtual float rootChunkError( const Qgs3DMapSettings &map ) const override;
    virtual void rootChunkHeightRange( float &hMin, float &hMax ) const override;
    virtual float heightAt( double x, double y, const Qgs3DRenderContext &context ) const override;
    virtual void writeXml( QDomElement &elem ) const override;
    virtual void readXml( const QDomElement &elem ) override;
    virtual void resolveReferences( const QgsProject &project ) override;
    virtual QgsChunkLoader *createChunkLoader( QgsChunkNode *node ) const override;
    // Root node has zoom=0, x=0, y=0.
    // It corresponds to a fake zoom=-1 tile for QgsTileMatrix
    virtual QgsChunkNode *createRootNode() const override;
    virtual QVector<QgsChunkNode *> createChildren( QgsChunkNode *node ) const override;

    /**
     * Set layer to take tiles from
     * \returns true on success
     */
    bool setLayer( QgsTiledSceneLayer *layer );
    //! Returns the layer we take tiles from
    QgsTiledSceneLayer *layer() const;

  private:
    QgsMapLayerRef mLayerRef;
    std::optional<QgsQuantizedMeshMetadata> mMetadata;
    QgsCoordinateTransform mTileCrsToMapCrs;
    QgsTiledSceneIndex mIndex;
    QgsRectangle mMapExtent;

    QgsQuantizedMeshTerrainGenerator( QgsMapLayerRef layerRef, const QgsQuantizedMeshMetadata &metadata );
    QgsTileXYZ nodeIdToTile( QgsChunkNodeId nodeId ) const;
};
