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

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

/*  CCOPYRIGHT  */

#include "normalview.h"
#include "viewshape.h"
#include "viewdata.h"
#include <vtkPolyData.h>
#include <vtkImageData.h>
#include <vtkRenderWindow.h>
#include <vtkPlane.h>
#include <vtkLineSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkProperty.h>
#include <vtkRendererCollection.h>
#include <vtkCamera.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkAxesActor.h>

using namespace NEWMAT;

NormalView::NormalView(vtkSmartPointer<vtkCamera> camera, vtkSmartPointer<vtkRenderWindow> renderwindow)
{
    ColumnVector initnormal(3);
    initnormal << 1.0 << 0.0 << 0.0;
    ColumnVector initviewup(3);
    initviewup << 0.0 << 0.0 << 1.0;
    CreateView(initnormal, initviewup, camera, renderwindow);
}

vtkSmartPointer<vtkRenderWindow> NormalView::GetView()
{
    return m_views[0].renderWindow;
}

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

//void NormalView::SetupOrientationWidget(vtkSmartPointer<vtkRenderWindowInteractor> interactor)
//{
//    auto axes = vtkSmartPointer<vtkAxesActor>::New();
//    axes->SetPosition(100, 100, 100);
//    m_orientationWidget = vtkSmartPointer<vtkOrientationMarkerWidgetFixed>::New();
//    m_orientationWidget->SetOrientationMarker(axes);
//    m_orientationWidget->SetInteractor(interactor);
//}

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

    if (m_markerShape)
    {
        ColumnVector point = m_markerShape->GetPoint(m_markerPointId);
        ColumnVector normal = m_markerShape->GetNormal(m_markerPointId);
        ColumnVector center = m_markerShape->GetCenter();
        ColumnVector delta = point - center;
        delta /= std::sqrt(delta(1) * delta(1) + delta(2) * delta(2) + delta(3) * delta(3));
        ColumnVector planenormal(3);
        planenormal << normal(2) * delta(3) - normal(3) * delta(2)
                    << normal(3) * delta(1) - normal(1) * delta(3)
                    << normal(1) * delta(2) - normal(2) * delta(1);

        m_views[0].plane->SetOrigin(point.Store());
        m_views[0].plane->SetNormal(planenormal.Store());
        m_views[0].camera->SetViewUp(normal.Store());

        PlanesChanged();
    }
}

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

    if (m_markerShape)
    {
        ColumnVector point =  m_markerShape->GetPoint(m_markerPointId);
        ColumnVector normal = m_markerShape->GetNormal(m_markerPointId);
        ColumnVector point1 = point - 5 * normal;
        ColumnVector point2 = point + 5 * normal;

        auto normalsource = vtkSmartPointer<vtkLineSource>::New();
        normalsource->SetPoint1(point1.Store());
        normalsource->SetPoint2(point2.Store());
        auto normalmapper = vtkSmartPointer<vtkPolyDataMapper>::New();
        normalmapper->SetInputConnection(normalsource->GetOutputPort());
        auto normalactor = vtkSmartPointer<vtkActor>::New();
        normalactor->SetMapper(normalmapper);
        normalactor->GetProperty()->SetColor(1.0, 0.0, 0.0);
        auto normalrenderer = vtkSmartPointer<vtkRenderer>::New();
        normalrenderer->SetLayer(vw.renderWindow->GetNumberOfLayers());
        normalrenderer->AddActor(normalactor);
        vw.renderWindow->SetNumberOfLayers(vw.renderWindow->GetNumberOfLayers() + 1);
        vw.renderWindow->AddRenderer(normalrenderer);
    }
}

void NormalView::SetupCameraForView(View& vw)
{
    ColumnVector center = m_markerShape->GetCenter();
    ColumnVector normal(3);
    normal << vw.plane->GetNormal();
    ColumnVector position = center + normal;
    vw.camera->SetFocalPoint(center.Store());
    vw.camera->SetPosition(position.Store());
    vw.camera->ParallelProjectionOn();
    ColumnVector bounds(6);
    bounds << m_markerShape->GetPolyData()->GetBounds();
    vw.camera->SetParallelScale(std::max(std::max(bounds(2) - bounds(1), bounds(4) - bounds(3)), bounds(6) - bounds(5)));
    vw.camera->Zoom(m_scale);
}

//void NormalView::SetupMarkersForView(View &vw)
//{
//    ViewBase::SetupMarkersForView(vw);

//    if (m_orientationWidget)
//    {
////        m_orientationWidget->SetEnabled(0);
//        m_orientationWidget->SetEnabled(1);
//        m_orientationWidget->InteractiveOff();
//    }
//}
