/* osgEarth
 * Copyright 2025 Pelican Mapping
 * MIT License
 */
#pragma once

#include <osgEarth/Common>
#include <osgEarth/ObjectIndex>
#include <osgEarth/Callbacks>

#include <osg/Image>
#include <osg/Texture2D>
#include <osgViewer/View>

namespace osgEarth { namespace Util
{
    /**
     * Picks objects that are encoded with ObjectIDs.
     * Usage: see osgearth_pick.cpp
     */
    class OSGEARTH_EXPORT ObjectIDPicker : public osg::Node
    {
    public:
        //! Construct a new picker
        ObjectIDPicker();

        //! View within which to pick
        void setView(osgViewer::View* view);
        osgViewer::View* getView() const { return _view.get(); }

        //! Scene graph from which to pick
        void setGraph(osg::Node*);
        osg::Node* getGraph() const { return _graph.get(); }

        //! Pixels on each side of the clicked pixel to check for hits.
        void setBuffer(int value) { _buffer = value; }
        int getBuffer() const { return _buffer; }

        //! Size of the RTT image (pixels per side) - must call before setView()
        void setRTTSize(int value) { _rttSize = value; }
        int getRTTSize() const { return _rttSize; }

        enum ActionType {
            ACTION_HOVER,
            ACTION_CLICK
        };

        using Function = std::function<void(ObjectID, ActionType)>;

        //! Function to call when the pick potentially changes.
        //! The parameters are Object ID and a bool which indicates a hover
        //! (true) or a click (false).
        Callback<void(ObjectID, ActionType)> onPick;

        //! Function to call when the user hovers an object
        //OE_DEPRECATED("Use onPick instead")
        Callback<void(ObjectID)> onHover;

        //! Function to call when the user clicks an object
        //OE_DEPRECATED("Use onPick instead")
        Callback<void(ObjectID)> onClick;

    public: // for debugging

        /** For debugging only - creates (if nec.) and returns a texture that captures
            the RTT image so you can display it. */
        osg::Texture2D* getOrCreateTexture();

    public: // osg::Node
        void traverse(osg::NodeVisitor&) override;

    protected:

        /** dtor */
        virtual ~ObjectIDPicker();

        osg::observer_ptr<osgViewer::View> _view;
        osg::ref_ptr<osg::Image> _pickImage;
        osg::ref_ptr<osg::Camera> _rtt;
        osg::ref_ptr<osg::Node> _graph;
        osg::ref_ptr<osg::Texture2D> _debugTex;

        void pick(osg::View* view, float x, float y, ActionType type);

        void setupRTT(osgViewer::View*);

        int _rttSize = 256; // size of the RTT image (pixels per side)
        int _buffer = 2; // buffer around pick point to check (pixels)

    };

} }
