// SPDX-License-Identifier: LGPL-2.1-or-later
//
// SPDX-FileCopyrightText: 2009 Torsten Rahn <tackat@kde.org>
//

#ifndef MARBLE_GEODATAREGION_H
#define MARBLE_GEODATAREGION_H

#include "GeoDataObject.h"

namespace Marble
{

class GeoDataFeature;
class GeoDataLatLonAltBox;
class GeoDataLod;
class GeoDataRegionPrivate;

/*!
    \class GeoDataRegion
    \brief GeoDataRegion describes the visibility and extent of a feature.

    GeoDataRegion is a tool class that implements the Region tag/class
    of the Open Geospatial Consortium standard KML 2.2.

    GeoDataRegion provides all aspects that can be taken into account to find
    out whether a GeoDataFeature (or a GeoDataLink) is visible on the map:

    \li On one hand GeoDataRegion owns a GeoDataLatLon(Alt)Box object.
        GeoDataLatLon(Alt)Box is a bounding box in geodesic coordinates.
        As such GeoDataLatLon(Alt)Box allows to determine whether the feature is
        located inside the area that the observer/camera is looking at
        ("viewLatLonAltBox").
    \li Additionally GeoDataRegion has got a GeoDataLod ("Level of Detail")
        object. GeoDataLod describes the least and maximum size on the
        screen that is required to consider a feature to be active.

     A feature is visible if it's active and if its latLonAltBox covers the area
     that is being looked at by the observer.
*/

class GEODATA_EXPORT GeoDataRegion : public GeoDataObject
{
public:
    /*!
        \brief Creates a new GeoDataRegion object that is not assigned to a \a feature.
        Naturally it's recommended to assign a feature or a link to the region (and
        therefore it's recommended to use one of the other constructors instead).
        This constructor allows to create a stand alone region which can get
        assigned to the feature or link later on.
    */
    GeoDataRegion();

    /*!
        \brief Creates a new GeoDataRegion as a copy of \p other.
    */
    GeoDataRegion(const GeoDataRegion &other);

    /*!
        \brief Creates a new GeoDataRegion object that is associated to a \a feature.
        In the model the feature represents the parent object of the region.
    */
    explicit GeoDataRegion(GeoDataFeature *feature);

    /*!
        \brief Destroys a Region object.
    */
    ~GeoDataRegion() override;

    /*!
        \brief Provides type information for downcasting a GeoNode
    */
    const char *nodeType() const override;

    bool operator==(const GeoDataRegion &other) const;
    bool operator!=(const GeoDataRegion &other) const;

    /*!
        \brief Returns a geodesic bounding box ("latLonAltBox") of the region.
        Returns a geodesic bounding box that describes the extent of a feature or
        a link.
        If no latLonAltBox has been set then a GeoDataLatLonAltBox object
        will be calculated automatically: If the associated parent object is
        a feature then the geometry that might be associated to the feature
        will be used to calculate the GeoDataLatLonAltBox. Otherwise the
        coordinate will be used to create a GeoDataLatLonAltBox (in case that
        there is no geometry assigned to the feature or if the parent object of the
        region is a GeoDataLink).
    */
    const GeoDataLatLonAltBox &latLonAltBox() const;

    /*!
        \brief Sets the \a latLonAltBox of the region.
        Sets the geodesic bounding box that describes the extent of a feature or
        a link.
    */
    void setLatLonAltBox(const GeoDataLatLonAltBox &latLonAltBox);

    /*!
        \brief Returns the region's level of detail.
        The level of detail is returned as a \a lod object.
        If no \a lod has been set then a GeoDataLod object with default values
        is being returned.
    */
    GeoDataLod &lod() const;

    /*!
        \brief Sets a region's level of detail.
        The level of detail is set as a \a lod object.
    */
    void setLod(const GeoDataLod &lod);

    // Serialization
    /*!
        \brief Serialize the Region to a stream.
        \param stream the stream.
    */
    void pack(QDataStream &stream) const override;

    /*!
        \brief Unserialize the Region from a stream.
        \param stream the stream.
    */
    void unpack(QDataStream &stream) override;

    GeoDataRegion &operator=(const GeoDataRegion &other);

private:
    void swap(GeoDataRegion &other);
    GeoDataRegionPrivate *d;
};

}

#endif
