/*
 * Tools related to the MitoPacq, the CBIA time-lapse cell observation simulator.
 *
 * Copyright (C) 2005-2013   Centre for Biomedical Image Analysis (CBIA)
 *
 * This library-related tools is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <iostream>
#include <i3d/image3d.h>


using std::cout;
using std::endl;

template <class MT,class FT>
void ApplyMask(const MT *m,const MT ID, FT *f,const size_t l) {
	for (size_t i=0; i < l; ++i) {
		if (*m != ID) *f=0;

		++m; ++f;
	}
}

int main(int argc, char* argv[]) {
    cout << argv[0] << " - part of the tools set of the OpticalFlow library \n"
         "Copyright (C) 2005-2013 Centre for Biomedical Image Analysis (CBIA)\n"
         "This is free software; see the source for copying conditions. "
         "There is NO\nwarranty; not even for MERCHANTABILITY or FITNESS FOR "
         "A PARTICULAR PURPOSE.\n\n";

	//type of images
	typedef i3d::GRAY16 MT; //mask
	typedef float FT;	//flow field

	if (argc < 5) {
		cout << "Program extracts given xy-slice from all flow field images it finds in the current directory\n";
		cout << "and belonging to some cell (via its ID).\n";
		cout << "If mask image is supplied, it also reads mask images and crops flow fields according to it.\n\n";
		cout << "Syntax:\n";
		cout << "  " << argv[0] << " ID starting_index ending_index z_index apply_mask\n";
		return(1);
	}

	//input params...
	const size_t ID=atol(argv[1]);
	const size_t countFrom=atol(argv[2]);
	const size_t countTo=atol(argv[3]);
	const size_t zIndex=atol(argv[4]);

	//MAIN CYCLE
	//span of processed files
	for (size_t T=countFrom; T <= countTo; ++T) {
		try {
			//open flow fields, per partes
			char fn[50];
			sprintf(fn,"ID%02ld_T%03ld_FF_finalGlobal_X.ics",ID,T);
			cout << "reading flow field: " << fn << endl;

			//X-element_part1
			i3d::Image3d<FT> FF(fn);
			i3d::Image3d<FT> slice;
			FF.GetSliceZ(slice,zIndex);

			//Y-element_part1
			sprintf(fn,"ID%02ld_T%03ld_FF_finalGlobal_Y.ics",ID,T);
			cout << "reading flow field: " << fn << endl;
			FF.ReadImage(fn);

			//X-element_part2
			i3d::Image3d<MT> mask;
			if (argc > 5) {
				sprintf(fn,"sceneMasks%03ld.ics",T);
				cout << "appling mask image: " << fn << endl;
				mask.ReadImage(fn);

				ApplyMask(mask.GetVoxelAddr(0,0,zIndex),(MT)ID,
					slice.GetFirstVoxelAddr(),slice.GetImageSize());
			}

			sprintf(fn,"ID%02ld_T%03ld_FF_finalGlobal_X_z%02ld.ics",ID,T,zIndex);
			slice.SaveImage(fn);

			//Y-element_part2
			FF.GetSliceZ(slice,zIndex);
			if (argc > 5) {
				ApplyMask(mask.GetVoxelAddr(0,0,zIndex),(MT)ID,
					slice.GetFirstVoxelAddr(),slice.GetImageSize());
			}

			sprintf(fn,"ID%02ld_T%03ld_FF_finalGlobal_Y_z%02ld.ics",ID,T,zIndex);
			slice.SaveImage(fn);

			//extract and save the slice from the mask image as well
			if (argc > 5) {
				i3d::Image3d<MT> sliceM;
				mask.GetSliceZ(sliceM,zIndex);

				//extract only mask of the given cell
				//and "make it visible"
				MT* p=sliceM.GetFirstVoxelAddr();
				MT* const pL=p+sliceM.GetImageSize();
				while (p != pL) {
					*p=(*p == ID)? 100 : 0;
					++p;
				}

				sprintf(fn,"ID%02ld_T%03ld_cellMask_z%02ld.ics",ID,T,zIndex);
				sliceM.SaveImage(fn);
			}
		}
		catch (i3d::IOException& e)
		{
			cout << "skipping time point " << T << endl;
		}
		//quits on any other exception...
	}

	return(0);
}
