#pragma once

#ifndef SUBCAMERAMANAGER_INCLUDED
#define SUBCAMERAMANAGER_INCLUDED

#include "tgeometry.h"

//==============================================================================

//  Forward declarations
class QMouseEvent;
class QPaintEvent;
class SceneViewer;
class QPoint;

//==============================================================================

//=====================================
//    SceneViewerInteractiveGadget
//-------------------------------------

/*!
  SceneViewerInteractiveGadget constitutes the base class for implementing
  objects that use the SceneViewer for user editing.
  The class contains the basic QEvent-related methods that a SceneViewer
  will invoke once an instance of this class has been assigned to it.
  The class implements a priority number which identifies the precedence
  between gadgets. Lower priority gadgets interact later and are drawn before
  with respect to higher priority ones.
  Interaction methods such as mouse events also return a boolean to specify
  whether
  the event allows further processing of lower priority gadgets.
  \note Under development yet.
*/
class SceneViewerInteractiveGadget {
public:
  virtual int getPriority() const { return 0; }

  virtual bool mousePressEvent(SceneViewer *viewer, QMouseEvent *me) {
    return true;
  }
  virtual bool mouseMoveEvent(SceneViewer *viewer, QMouseEvent *me) {
    return true;
  }
  virtual bool mouseReleaseEvent(SceneViewer *viewer, QMouseEvent *me) {
    return true;
  }

  virtual void draw(SceneViewer *viewer, QPaintEvent *pe) {}
};

//==============================================================================

//================================
//    PreviewSubCameraManager
//--------------------------------

class PreviewSubCameraManager final : public SceneViewerInteractiveGadget {
  TRect m_editingInterestRect;
  UCHAR m_dragType;
  bool m_clickAndDrag;

  QPointF m_mousePressPos;
  TPointD m_cameraMousePressPos;
  bool m_mousePressed;

public:
  enum EditPreviewDrag {
    NODRAG       = 0x0,
    OUTER_LEFT   = 0x1,
    INNER_LEFT   = 0x2,
    OUTER_RIGHT  = 0x4,
    INNER_RIGHT  = 0x8,
    OUTER_TOP    = 0x10,
    INNER_TOP    = 0x20,
    OUTER_BOTTOM = 0x40,
    INNER_BOTTOM = 0x80,
    OUTER        = OUTER_LEFT | OUTER_RIGHT | OUTER_TOP | OUTER_BOTTOM,
    INNER        = INNER_LEFT | INNER_RIGHT | INNER_TOP | INNER_BOTTOM,
    DRAG_LEFT    = OUTER_LEFT | INNER,
    DRAG_RIGHT   = OUTER_RIGHT | INNER,
    DRAG_TOP     = OUTER_TOP | INNER,
    DRAG_BOTTOM  = OUTER_BOTTOM | INNER
  };

  PreviewSubCameraManager();
  ~PreviewSubCameraManager();

public:
  static PreviewSubCameraManager *instance();

  UCHAR getDragType() const { return m_dragType; }
  void setDragType(UCHAR dragType) { m_dragType = dragType; }

  TRect getEditingCameraInterestRect() const;
  void setEditingCameraInterestRect(const TRect &rect) {
    m_editingInterestRect = rect;
  }

  TRectD getEditingCameraInterestStageRect() const;

  bool mousePressEvent(SceneViewer *viewer, const TMouseEvent &event);
  bool mouseMoveEvent(SceneViewer *viewer, const TMouseEvent &event);
  bool mouseReleaseEvent(SceneViewer *viewer);

  void deleteSubCamera(SceneViewer *viewer);

private:
  TPointD winToCamera(SceneViewer *viewer, const QPointF &pos) const;
  TPointD cameraToWin(SceneViewer *viewer, const TPointD &cameraPos) const;

  UCHAR getSubCameraDragEnum(SceneViewer *viewer, const QPointF &mousePos);
  TPoint getSubCameraDragDistance(SceneViewer *viewer, QPointF &mousePos);
};

#endif  // SUBCAMERAMANAGER_INCLUDED
