/* -*- mia-c++  -*-
 *
 * This file is part of MIA - a toolbox for medical image analysis 
 * Copyright (c) Leipzig, Madrid 1999-2017 Gert Wollny
 *
 * MIA is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with MIA; if not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <sstream>
#include <cassert>
#include <algorithm>
#include <mia/core/file.hh>
#include <mia/core/filter.hh>
#include <mia/core/msgstream.hh>
#include <mia/2d/vfio.hh>

#include <vistaio/vista4mia.hh>

NS_BEGIN(vista_2dvf_io)

NS_MIA_USE

using namespace std;
using namespace boost;

class CVista2DVFIOPlugin : public C2DVFIOPlugin {
public:
	CVista2DVFIOPlugin();
private:
	PData do_load(const string& fname) const;
	bool do_save(const string& fname, const Data& data) const;
	const string do_get_descr() const;
};

CVista2DVFIOPlugin::CVista2DVFIOPlugin():
	C2DVFIOPlugin("vista")
{
	add_supported_type(it_float);
	add_suffix(".v");
	add_suffix(".vf");
	add_suffix(".V");
	add_suffix(".VF");
	
	add_standard_vistaio_properties(*this); 

}

CVista2DVFIOPlugin::PData  CVista2DVFIOPlugin::do_load(const string& fname) const
{
	CInputFile f(fname);

	VistaIOAttrList vlist = VistaIOReadFile(f,NULL);

	VistaIOResetProgressIndicator();

	if (!vlist)
		return CVista2DVFIOPlugin::PData();

	CVista2DVFIOPlugin::PData result;
	VistaIOAttrListPosn posn;

	for (VistaIOFirstAttr(vlist, &posn); VistaIOAttrExists(&posn) && !result; VistaIONextAttr(&posn)) {
		if (VistaIOGetAttrRepn(&posn) != VistaIOField2DRepn)
			continue;

		VistaIOField2D field = NULL;
		VistaIOGetAttrValue(&posn, 0, VistaIOField2DRepn, &field);

		if (!field)
			throw runtime_error(fname + "looked like a vector field, but is none");

		if (field->nsize_element != 2)
			throw runtime_error(fname + "is not a field of 2D vectors");

		if (field->repn != VistaIOFloatRepn) {
			cvdebug() << "Skipping input field, which is not of type float\n";
			continue;
		}


		result = CVista2DVFIOPlugin::PData(new C2DIOVectorfield(C2DBounds(field->x_dim, field->y_dim)));
		T2DVector<VistaIOFloat> * input  = (T2DVector<VistaIOFloat> *)field->p.data;
		copy(input, input + result->size(), result->begin());
		copy_attr_list(*result, field->attr);
	}


	VistaIODestroyAttrList(vlist);
	return result;
}


bool CVista2DVFIOPlugin::do_save(const string& fname, const C2DIOVectorfield& data) const
{

	COutputFile f(fname);

	VistaIOAttrList vlist = VistaIOCreateAttrList();
	VistaIOField2D out_field = VistaIOCreateField2D(data.get_size().x,
					    data.get_size().y,
					    2,
					    VistaIOFloatRepn);
	T2DVector<VistaIOFloat> * output  = (T2DVector<VistaIOFloat> *)out_field->p.data;
	copy(data.begin(), data.end(), output);

	copy_attr_list(out_field->attr, data);
	VistaIOSetAttr(vlist, "2DFVectorfield", NULL, VistaIOField2DRepn, out_field);

	bool result = VistaIOWriteFile(f,vlist);
	VistaIODestroyAttrList(vlist);

	return result;
}

const string CVista2DVFIOPlugin::do_get_descr() const
{
	return "a 2d vector field io plugin for vista";
}

extern "C" EXPORT  CPluginBase *get_plugin_interface()
{
	C2DFVectorTranslator::register_for("pixel");
	return new CVista2DVFIOPlugin();
}

NS_END
