/* osgEarth
 * Copyright 2025 Pelican Mapping
 * MIT License
 */
#pragma once
#include <osgEarth/MapNode>
#include <osgEarth/FeatureNode>
#include <osgEarth/Style>
#include <osgEarth/Callbacks>
#include <osg/Group>
#include <osgGA/GUIEventHandler>

namespace osgEarth { namespace Contrib
{
    using namespace osgEarth;

    /**
     * Tool that lets the user draw a GeoExtent, and fire a callback
     * when it is done.
     */
    struct OSGEARTH_EXPORT SelectExtentTool : public osgGA::GUIEventHandler
    {
    public:
        //! Construct a new tool
        SelectExtentTool(MapNode* mapNode);

        //! Whether this tool is enabled (default is true)
        void setEnabled(bool value);
        bool getEnabled() const { return _enabled; }

        //! Clear the visual bounding box
        void clear();

        //! Sets the mouse button that activates the tool
        //! (osgGA::GUIEventAdapter::MouseButtonMask)
        void setMouseButtonMask(int value);

        //! Sets the mod key mask (shift, ctrl, alt) that activates the tool
        //! (osgGA::GUIEventAdapter::ModKeyMask)
        void setModKeyMask(int value);

        //! Access the style to change the appearance of the box
        Style& getStyle();

        //! Function to call when the user finished drawing the extent
        //! or the user clicks without the configured masks
        osgEarth::Callback<void(const GeoExtent&)> onSelect;

    public: // osgGA::GUIEventHandler

        bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) override;

    protected:

        bool _enabled = true;
        bool _mouseDown = false;
        int _mouseButtonMask = osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON;
        int _modKeyMask = 0;
        bool _featureVisible = true;

        osg::ref_ptr<osg::Group> _root;
        GeoPoint _mouseDownPoint;
        GeoExtent _extent;
        osg::ref_ptr<osgEarth::FeatureNode> _featureNode;
        osg::ref_ptr<osgEarth::Feature> _feature;
        osg::observer_ptr< MapNode > _mapNode;

        MapNode* getMapNode() { return _mapNode.get(); }

        void rebuild();

        void updateFeature(const GeoExtent& ex);
    };
} }
