/* ============================================================
 *
 * This file is a part of digiKam project
 * https://www.digikam.org
 *
 * Date        : 2023-05-15
 * Description : geolocation engine based on Marble.
 *               (c) 2007-2022 Marble Team
 *               https://invent.kde.org/education/marble/-/raw/master/data/credits_authors.html
 *
 * SPDX-FileCopyrightText: 2023-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
 *
 * SPDX-License-Identifier: LGPL-2.1-or-later
 *
 * ============================================================ */

#pragma once

class QUrl;
class QString;

namespace Marble
{

class GeoSceneTileDataset;
class TileId;

class ServerLayout
{
public:

    explicit ServerLayout(GeoSceneTileDataset* textureLayer);
    virtual ~ServerLayout();

    /**
     * Translates given tile @p id using a @p prototypeUrl into an URL
     * that can be used for downloading.
     *
     * @param prototypeUrl prototype URL, to be completed by this method
     * @param id Marble-specific ID of requested tile
     * @return completed URL for requested tile id
     */
    virtual QUrl downloadUrl(const QUrl& prototypeUrl, const TileId& id) const = 0;

    /**
     * Returns the name of the server layout to be used as the value in the
     * mode attribute in the DGML file.
     */
    virtual QString name() const = 0;

    /**
     * Returns the sourceDir of the texture layer, or an empty string if the texture layer is 0
     */
    QString sourceDir() const;

protected:

    GeoSceneTileDataset* const m_textureLayer = nullptr;
};

class MarbleServerLayout : public ServerLayout
{
public:

    explicit MarbleServerLayout(GeoSceneTileDataset* textureLayer);

    /**
     * Completes the path of the @p prototypeUrl and returns it.
     */
    QUrl downloadUrl(const QUrl& prototypeUrl, const TileId&) const override;

    QString name() const override;
};

class OsmServerLayout : public ServerLayout
{
public:

    explicit OsmServerLayout(GeoSceneTileDataset* textureLayer);

    /**
     * Appends %zoomLevel/%x/%y.%suffix to the path of the @p prototypeUrl and returns
     * the result.
     */
    QUrl downloadUrl(const QUrl& prototypeUrl, const TileId&) const override;

    QString name() const override;
};

class CustomServerLayout : public ServerLayout
{
public:

    explicit CustomServerLayout(GeoSceneTileDataset* texture);

    /**
     * Replaces escape sequences in the @p prototypeUrl by the values in @p id
     * and returns the result.
     *
     * Escape sequences are: {zoomLevel}, {x}, and {y}.
     */
    QUrl downloadUrl(const QUrl& prototypeUrl, const TileId& id) const override;

    QString name() const override;
};

class WmsServerLayout : public ServerLayout
{
public:

    explicit WmsServerLayout(GeoSceneTileDataset* texture);

    /**
     * Adds WMS query items to the @p prototypeUrl and returns the result.
     *
     * The following items are added: service, request, version, width, height, bbox.
     *
     * The following items are only added if they are not already specified in the dgml file:
     * styles, format, srs, layers.
     */
    QUrl downloadUrl(const QUrl& prototypeUrl, const Marble::TileId& tileId) const override;

    QString name() const override;

    QString epsgCode() const;
};

class WmtsServerLayout : public ServerLayout
{
public:

    explicit WmtsServerLayout(GeoSceneTileDataset* texture);

    /**
     * Adds WMTS query items to the @p prototypeUrl and returns the result.
     */
    QUrl downloadUrl(const QUrl& prototypeUrl, const Marble::TileId& tileId) const override;

    QString name() const override;

    QString epsgCode() const;
};

class QuadTreeServerLayout : public ServerLayout
{
public:

    explicit QuadTreeServerLayout(GeoSceneTileDataset* textureLayer);
    QUrl downloadUrl(const QUrl&, const Marble::TileId&) const override;

    QString name() const override;

private:

    static QString encodeQuadTree(const Marble::TileId&);
};

class TmsServerLayout : public ServerLayout
{
public:

    explicit TmsServerLayout(GeoSceneTileDataset* textureLayer);

    /**
     * Appends %zoomLevel/%x/2^%zoomLevel-%y-1.%suffix to the path of the @p prototypeUrl and returns
     * the result.
     * TMS (TileMapService) maps take the origin for y coordinate at the bottom of the map,
     * as opposed to what Marble and OpenStreepMap (SlippyTiles) do.
     */
    QUrl downloadUrl(const QUrl& prototypeUrl, const TileId&) const override;

    QString name() const override;
};

} // namespace Marble
