/*
*
*  $Id: iimageexportcontract.cpp $
*  Ginkgo CADx Project
*
*  Copyright 2008-14 MetaEmotion S.L. All rights reserved.
*  http://ginkgo-cadx.com
*
*  This file is licensed under LGPL v3 license.
*  See License.txt for details
*
*/
#include "iimageexportcontract.h"

#include <api/istudycontext.h>
#include <api/iwidgetsmanager.h>
#include <api/icontexto.h>
#include <api/iwidgetsrenderer.h>
#include <api/ivista.h>
#include <main/controllers/controladorcarga.h>

#include <vtkSmartPointer.h>
#include <vtkObject.h>
#include <vtkRenderer.h>
#include <vtkPointData.h>
#include <vtkImageData.h>
#include <vtkMatrix4x4.h>
#include <vtkImageReslice.h>
#include <vtkImageMapToRGBA.h>
#include <vtkExecutive.h>
#include <vtkInformationVector.h>
#include <vtkAlgorithmOutput.h>
#include <vtkInformation.h>
#include <itkVectorResampleImageFilter.h>

#include <itk/itkVTKImageToImageFilter.h>

GNC::GCS::IImageExportDelegate::IImageExportDelegate(IImageExportContract* exportContract): ExportContract(exportContract)
{

}

GNC::GCS::IImageExportDelegate::~IImageExportDelegate()
{

}

std::string GNC::GCS::IImageExportDelegate::GetPathActiveDICOM()
{
	return ExportContract->GetView()->GetEstudio()->GetPathActiveImage();
}

std::string GNC::GCS::IImageExportDelegate::GetPathDICOM(int index)
{
	return ExportContract->GetView()->GetEstudio()->GetImagePath(index);
}

std::list<std::string> GNC::GCS::IImageExportDelegate::GetPathAllDICOMs()
{
	return ExportContract->GetView()->GetImagePaths();
}

GNC::GCS::IImageExportContract* GNC::GCS::IImageExportDelegate::GetExportContract()
{
	return ExportContract;
}

void GNC::GCS::IImageExportDelegate::CopyRGBToRGBA32(unsigned char* src, unsigned char* dst, unsigned int size)
{
	for (unsigned int off = 0; off < size; ++off) {
		dst[0] = src[2];
		dst[1] = src[1];
		dst[2] = src[0];
		dst[3] = 255;
		src+=3;
		dst+=4;
	}
}
void GNC::GCS::IImageExportDelegate::CopyRGBA32ToRGB(unsigned char* src, unsigned char* dst, unsigned int size)
{
	for (unsigned int off = 0; off < size; ++off) {
		dst[0] = src[2];
		dst[1] = src[1];
		dst[2] = src[0];
		src+=4;
		dst+=3;
	}
}

vtkSmartPointer<vtkImageData> GNC::GCS::IImageExportDelegate::GetVtkImage(int index)
{
	GNC::GCS::IStreamingLoader* Loader = GNC::GCS::ControladorCarga::Instance()->NewLoader();

	Loader->SetInput(GetPathDICOM(index));

	Loader->Update();
	vtkSmartPointer<vtkImageData> pImgData;
	Loader->GetOutputCopy(pImgData);
	delete Loader;
	
	return pImgData;
}

void GNC::GCS::IImageExportDelegate::Print(vtkSmartPointer<vtkImageData> imageData, bool conWidgets, int index, const GNC::GCS::Vector& size, GNC::GCS::IImageExportDelegate::ImageType::Pointer& out, GNC::GCS::IWidgetsManager* pWidgetsManager)
{
	typedef itk::VTKImageToImageFilter<GNC::GCS::IImageExportDelegate::ImageType> TipoFiltro;
	typedef itk::VectorResampleImageFilter<GNC::GCS::IImageExportDelegate::ImageType, GNC::GCS::IImageExportDelegate::ImageType> TipoResampler;

	TipoFiltro::Pointer VTK2ITKfiltro =  TipoFiltro::New();
	TipoResampler::Pointer resampler = TipoResampler::New();

	VTK2ITKfiltro->SetInput(imageData);
	VTK2ITKfiltro->GetImporter()->Update();

	resampler->SetInput(VTK2ITKfiltro->GetImporter()->GetOutput());

	GNC::GCS::Vector aspectRatio(1.0f, 1.0f);
	
	resampler->SetOutputOrigin(resampler->GetInput()->GetOrigin());
	resampler->SetOutputDirection(resampler->GetInput()->GetDirection());
	out = resampler->GetOutput();

	
	TipoResampler::InputImageType::SizeType origsize = resampler->GetInput()->GetLargestPossibleRegion().GetSize();			
	TipoResampler::InputImageType::SpacingType origspacing = resampler->GetInput()->GetSpacing();

	TipoResampler::InputImageType::SizeType newsize;
	TipoResampler::InputImageType::SpacingType newspacing;

	//apply spacing to scale pixels...
	GNC::GCS::Vector vOrigSize, vNewSize;
	
	if (!size.EsNaN()) {
		vOrigSize = GNC::GCS::Vector(origsize[0], (origspacing[1]/origspacing[0])*origsize[1]);
		vNewSize = vOrigSize.AjusteInteriorProporcional(size);
		aspectRatio = vNewSize / vOrigSize;
		aspectRatio.y = (origspacing[1]/origspacing[0]) * aspectRatio.y;
	} else {
		if (origsize[0] > origsize[1]) {
			vNewSize = GNC::GCS::Vector(origsize[0], (origspacing[1]/origspacing[0])*origsize[1]);
			aspectRatio.x = 1;
			aspectRatio.y = (origspacing[1]/origspacing[0]);
		} else {
			vNewSize = GNC::GCS::Vector((origspacing[0]/origspacing[1]) * origsize[0], origsize[1]);
			aspectRatio.x = (origspacing[0]/origspacing[1]);
			aspectRatio.y = 1;
		}
	}
	newspacing[0] = origspacing[0] / aspectRatio.x;
	newspacing[1] = origspacing[1] / aspectRatio.y;

	newsize[0] = (int) vNewSize.x;
	newsize[1] = (int) vNewSize.y;

	resampler->SetSize( newsize );
	resampler->SetOutputSpacing(newspacing);

	resampler->UpdateLargestPossibleRegion();
	
	if(conWidgets){
		PrintWithWidgets(out, index, aspectRatio, pWidgetsManager);
	}	
}

void GNC::GCS::IImageExportDelegate::PrintWithWidgets(ImageType::Pointer& img, int index, const GNC::GCS::Vector& aspectRatio, GNC::GCS::IWidgetsManager* pWidgetsManager)
{
	int dim[3];
	dim[0] = img->GetLargestPossibleRegion().GetSize()[0];
	dim[1] = img->GetLargestPossibleRegion().GetSize()[1];
	dim[2] = 1;

	unsigned char* imgptr = (unsigned char*) (img->GetPixelContainer()->GetImportPointer());
	unsigned int imgsize = dim[0] * dim[1];

	GNC::GCS::Contexto3D c;
	c.ancho = dim[0];
	c.alto = dim[1];

	c.spacing[0] = img->GetSpacing()[0];
	c.spacing[1] = img->GetSpacing()[1];
	c.spacing[2] = 1.0f;

	c.origin[0] = img->GetOrigin()[0];
	c.origin[1] = img->GetOrigin()[1];
	c.origin[2] = 0.0f;

	c.OVID = index;
	c.pRenderer = NULL;
	c.pOffscrenViewer =  NULL;

	c.CrearOffscreen();
	
	c.factorReescalado = aspectRatio;

	CopyRGBToRGBA32(imgptr, c.pixelData, imgsize);
	pWidgetsManager->OffScreenRender(&c);
	CopyRGBA32ToRGB(c.pixelData, imgptr, imgsize);

	c.DestruirOffscreen();
}

GNC::GCS::IImageExportContract::IImageExportContract()
{

}

GNC::GCS::IImageExportContract::~IImageExportContract()
{

}
