// 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
