/*  Multimodal Image Segmentation Tool (MIST)  */
/*  Eelke Visser  */

/*  Copyright (c) 2016 University of Oxford  */

/*  CCOPYRIGHT  */

#ifndef VIEWBASE_H
#define VIEWBASE_H

#include <memory>
#include <vector>
#include <vtkSmartPointer.h>
#include <vtkType.h>

#include <newmat.h>

class vtkLookupTable;
class vtkPlane;
class vtkPolyData;
class vtkRenderer;
class vtkRenderWindow;
class vtkCamera;
class ViewShape;
class ViewData;

class ViewBase
{
public:
    enum HideMode
    {
        HideNone,
        HideMarkers,
        HideAllOverlays
    };

    ViewBase();
    void ResetDataAndShapes();
    void AddShape(std::shared_ptr<ViewShape> shape);
    void SetData(std::shared_ptr<ViewData> data);
    void SetOverlay(std::shared_ptr<ViewData> overlay);
    void SetMarker(std::shared_ptr<ViewShape> shape, vtkIdType pointid);
    void SetMarkerTolerance(const double& value);
    double GetMarkerTolerance() const;
    void SetHideOverlays(HideMode value);
    HideMode GetHideOverlays();
    void SetScale(const double& scale);
    void ShowVertices(bool show);
    // TODO: Handle this properly (needed to handle changes in shapes)
    void RedrawMarkers();
    void Render();
    void ResetCameras();

protected:
    struct View
    {
        vtkSmartPointer<vtkPlane> plane;
        vtkSmartPointer<vtkRenderWindow> renderWindow;
        vtkSmartPointer<vtkCamera> camera;
        vtkSmartPointer<vtkPolyData> visibleVerts;
        vtkSmartPointer<vtkRenderer> markerRenderer;
    };

    std::vector<View> m_views;
    std::shared_ptr<ViewData> m_viewData;
    std::shared_ptr<ViewData> m_overlay;
    std::vector<std::shared_ptr<ViewShape> > m_shapes;

    double m_scale = 1.0;
    HideMode m_hideOverlays = HideNone;

    bool m_showVertices = true;
    std::shared_ptr<ViewShape> m_markerShape = nullptr;
    vtkIdType m_markerPointId = 0;
    double m_markerTolerance = 0.5;

    void CreateView(const NEWMAT::ColumnVector& normal, const NEWMAT::ColumnVector& viewup,
                    vtkSmartPointer<vtkCamera> camera, vtkSmartPointer<vtkRenderWindow> renderwindow);
    virtual void ContentsChanged();
    virtual void PlanesChanged();
    virtual void MarkerPointIDChanged();
    virtual void SetupSceneForView(View& vw);
    virtual void SetupCameraForView(View& vw);
    virtual void SetupMarkersForView(View& vw);
    void SetMarkerVisibilityForView(View& vw);
    vtkIdType Pick(View& vw, const double& x, const double& y);

private:
    ViewBase(const ViewBase&);
    ViewBase& operator=(const ViewBase&);
};

#endif // VIEWBASE_H
