// Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
//
// NVIDIA CORPORATION and its licensors retain all intellectual property
// and proprietary rights in and to this software, related documentation
// and any modifications thereto. Any use, reproduction, disclosure or
// distribution of this software and related documentation without an express
// license agreement from NVIDIA CORPORATION is strictly prohibited.
//
#pragma once

#include "AbstractGesture.h"
#include "AbstractItem.h"

OMNIUI_SCENE_NAMESPACE_OPEN_SCOPE

class ShapeGesture;

/**
 * @brief Base class for all the items that can be drawn and intersected with
 * mouse pointer.
 */
class OMNIUI_SCENE_CLASS_API AbstractShape : public AbstractItem
{
    OMNIUI_SCENE_OBJECT(AbstractShape);

public:
    OMNIUI_SCENE_API
    ~AbstractShape() override;

    OMNIUI_SCENE_API
    void destroy() override;

    /**
     * @brief All the gestures assigned to this shape
     */
    OMNIUI_SCENE_API
    const std::vector<std::shared_ptr<ShapeGesture>>& getGestures() const;

    /**
     * @brief Replace the gestures of the shape
     */
    OMNIUI_SCENE_API
    void setGestures(const std::vector<std::shared_ptr<ShapeGesture>>& gestures);

    /**
     * @brief Add a single gesture to the shape
     */
    OMNIUI_SCENE_API
    void addGesture(const std::shared_ptr<ShapeGesture>& gesture);

    OMNIUI_SCENE_API
    virtual void intersect(const Vector3 origin,
                           const Vector3 direction,
                           const Vector2 mouse,
                           const Matrix44& projection,
                           const Matrix44& view,
                           GestureState state) = 0;

    /**
     * @brief Contains all the information about the intersection
     */
    OMNIUI_SCENE_API
    virtual const AbstractGesture::GesturePayload* getGesturePayload() const = 0;

    /**
     * @brief Contains all the information about the intersection at the specific state
     */
    OMNIUI_SCENE_API
    virtual const AbstractGesture::GesturePayload* getGesturePayload(GestureState state) const = 0;

    /**
     * @brief The distance in pixels from mouse pointer to the shape for the intersection.
     */
    OMNIUI_SCENE_API
    virtual Float getIntersectionDistance() const;

protected:
    friend class ShapeGesture;

    OMNIUI_SCENE_API
    AbstractShape();

    OMNIUI_SCENE_API
    void _preDrawContent(
        const MouseInput& input, const Matrix44& projection, const Matrix44& view, float width, float height) override;

    void _collectManagers(std::unordered_set<GestureManager*>& managers) const override;

    void _cacheGesturePayload(const Vector3 origin,
                              const Vector3 direction,
                              const Vector2 mouse,
                              const Matrix44& projection,
                              const Matrix44& view,
                              GestureState state);

    std::vector<std::shared_ptr<ShapeGesture>> m_gestures;

    bool m_gesturePayloadCached = false;
};

OMNIUI_SCENE_NAMESPACE_CLOSE_SCOPE
