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

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

/*  CCOPYRIGHT  */

#include "orthoviews.h"
#include "viewshape.h"
#include "viewdata.h"
#include <newimageall.h>
#include <newmat.h>
#include <vtkPlane.h>
#include <vtkImageData.h>
#include <vtkRenderer.h>
#include <vtkRendererCollection.h>
#include <vtkRenderWindow.h>
#include <vtkCursor3D.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkActor.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkParallelCoordinatesInteractorStyle.h>
#include <vtkCamera.h>
#include <array>

using namespace NEWMAT;

OrthoViews::OrthoViews(vtkSmartPointer<vtkRenderWindow> sagittal, vtkSmartPointer<vtkRenderWindow> coronal,
                       vtkSmartPointer<vtkRenderWindow> transverse)
    : m_origin(3)
{
    ColumnVector sagittalnormal(3);
    sagittalnormal << 1.0 << 0.0 << 0.0;
    ColumnVector sagittalviewup(3);
    sagittalviewup << 0.0 << 0.0 << 1.0;
    CreateView(sagittalnormal, sagittalviewup, nullptr, sagittal);

    ColumnVector coronalnormal(3);
    coronalnormal << 0.0 << -1.0 << 0.0;
    ColumnVector coronalviewup(3);
    coronalviewup << 0.0 << 0.0 << 1.0;
    CreateView(coronalnormal, coronalviewup, nullptr, coronal);

    ColumnVector transversenormal(3);
    transversenormal << 0.0 << 0.0 << 1.0;
    ColumnVector transverseviewup(3);
    transverseviewup << 0.0 << 1.0 << 0.0;
    CreateView(transversenormal, transverseviewup, nullptr, transverse);

    ContentsChanged();

    m_cursor = vtkSmartPointer<vtkCursor3D>::New();
    m_cursor->OutlineOff();
    m_cursor->XShadowsOff();
    m_cursor->YShadowsOff();
    m_cursor->ZShadowsOff();
    m_origin = 0.0;
    OriginChanged();
}


void OrthoViews::OriginChanged()
{
    m_cursor->SetFocalPoint(m_origin.Store());

    for (auto it = m_views.begin(); it != m_views.end(); ++it)
        it->plane->SetOrigin(m_origin.Store());

    PlanesChanged();
}

ColumnVector OrthoViews::GetOrigin() const
{
    return m_origin;
}

void OrthoViews::SetOrigin(const ColumnVector& origin)
{
    m_origin = origin;
    OriginChanged();
}

ColumnVector OrthoViews::GetBounds() const
{
    ColumnVector bounds(6);
    if (m_viewData)
        bounds << m_viewData->GetImageData()->GetBounds();
    else
        bounds = 0.0;

    return bounds;
}

vtkSmartPointer<vtkRenderWindow> OrthoViews::GetSagittalView() const
{
    return m_views[0].renderWindow;
}

vtkSmartPointer<vtkRenderWindow> OrthoViews::GetCoronalView() const
{
    return m_views[1].renderWindow;
}

vtkSmartPointer<vtkRenderWindow> OrthoViews::GetTransverseView() const
{
    return m_views[2].renderWindow;
}

vtkIdType OrthoViews::PickSagittal(const double& x, const double& y)
{
    return ViewBase::Pick(m_views[0], x, y);
}

vtkIdType OrthoViews::PickCoronal(const double& x, const double& y)
{
    return ViewBase::Pick(m_views[1], x, y);
}

vtkIdType OrthoViews::PickTransverse(const double& x, const double& y)
{
    return ViewBase::Pick(m_views[2], x, y);
}

void OrthoViews::ContentsChanged()
{
    ViewBase::ContentsChanged();

    if (m_viewData)
        m_cursor->SetModelBounds(m_viewData->GetImageData()->GetBounds());
}

void OrthoViews::MarkerPointIDChanged()
{
    if (m_markerShape)
    {
        ColumnVector position(3);
        position << m_markerShape->GetPolyData()->GetPoint(m_markerPointId);
        m_origin = position;
        OriginChanged();
    }
}

void OrthoViews::SetupSceneForView(View& vw)
{
    ViewBase::SetupSceneForView(vw);

    auto cursormapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    cursormapper->SetInputConnection(m_cursor->GetOutputPort());
    auto cursoractor = vtkSmartPointer<vtkActor>::New();
    cursoractor->SetMapper(cursormapper);
    cursoractor->GetProperty()->SetColor(0.0, 1.0, 0.0);
    auto cursorrenderer = vtkSmartPointer<vtkRenderer>::New();
    cursorrenderer->SetLayer(vw.renderWindow->GetNumberOfLayers());
    cursorrenderer->AddActor(cursoractor);
    vw.renderWindow->SetNumberOfLayers(vw.renderWindow->GetNumberOfLayers() + 1);
    vw.renderWindow->AddRenderer(cursorrenderer);
}
