/*
 * 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 VOXEL>
bool PrintLine(i3d::Image3d<VOXEL> const &img,
					i3d::Vector3d<int> const &pos,
					i3d::Vector3d<int> const &dir,
					const int lStep, const int rStep) {

	bool printAdvice=false;

	cout << "\n# gnuplot datafile:\n";
	cout << "#x\ty\tz\tindex\tgray\n";
	for (int i=lStep; i <= rStep; ++i) {
		i3d::Vector3d<int> curPos(pos);
		curPos+=i*dir;

		if (img.Include(curPos)) {
			cout << curPos.x << "\t" << curPos.y << "\t" << curPos.z << "\t"
				  << i << "\t" << (float)img.GetVoxel(curPos) << "\n";
			printAdvice=true;
		}
	}

	return(printAdvice);
}

template <>
bool PrintLine(i3d::Image3d<i3d::RGB> const &img,
					i3d::Vector3d<int> const &pos,
					i3d::Vector3d<int> const &dir,
					const int lStep, const int rStep) {

	bool printAdvice=false;

	cout << "\n# gnuplot datafile:\n";
	cout << "#x\ty\tz\tindex\tgray\tr\tg\tb\n";
	for (int i=lStep; i <= rStep; ++i) {
		i3d::Vector3d<int> curPos(pos);
		curPos+=i*dir;

		if (img.Include(curPos)) {
			const int r=img.GetVoxel(curPos).red; 
			const int g=img.GetVoxel(curPos).green; 
			const int b=img.GetVoxel(curPos).blue; 
			const int gr=0.2126*(float)r + 0.7152*(float)g + 0.0722*(float)b;
			cout << curPos.x << "\t" << curPos.y << "\t" << curPos.z << "\t"
				  << i << "\t" << gr << "\t" << r << "\t" << g << "\t" << b << "\n";
			printAdvice=true;
		}
	}

	return(printAdvice);
}

template <>
bool PrintLine(i3d::Image3d<i3d::RGB16> const &img,
					i3d::Vector3d<int> const &pos,
					i3d::Vector3d<int> const &dir,
					const int lStep, const int rStep) {

	bool printAdvice=false;

	cout << "\n# gnuplot datafile:\n";
	cout << "#x\ty\tz\tindex\tgray\tr\tg\tb\n";
	for (int i=lStep; i <= rStep; ++i) {
		i3d::Vector3d<int> curPos(pos);
		curPos+=i*dir;

		if (img.Include(curPos)) {
			const int r=img.GetVoxel(curPos).red; 
			const int g=img.GetVoxel(curPos).green; 
			const int b=img.GetVoxel(curPos).blue; 
			const int gr=0.2126*(float)r + 0.7152*(float)g + 0.0722*(float)b;
			cout << curPos.x << "\t" << curPos.y << "\t" << curPos.z << "\t"
				  << i << "\t" << gr << "\t" << r << "\t" << g << "\t" << b << "\n";
			printAdvice=true;
		}
	}

	return(printAdvice);
}


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";

	if (argc != 10) {
		cout << "Bad number of parameters\nUsage: " << argv[0]
			  << " input_img pos_x pos_y pos_z dx dy dz l_step r_step\n";
		cout << "This will print values along a line throught the point [pos_x,pos_y,pos_z],\n"
			  << "the line will head in the direction (dx,dy,dz) and will span l/r-step\n"
			  << "times the length of the direction vector towards both ends.\n"
			  << "All numbers should be integers\n\n";
		cout << "example: " << argv[0] << " image.ics 25 25 10 1 0 0 -5 +5\n"
			  << "  to obtain a list of pixel values from the image.ics at positions\n"
			  << "  [25,25,10]+k*(1,0,0) where k=-5,-4,...,3,4,5\n";
		cout << "\nYou may want to pipe with    | tail -n+8 > data.dat\n";
				
		return(1);
	}

    i3d::ImgVoxelType vt = i3d::ReadImageType(argv[1]);
    std::cerr << "Voxel=" << VoxelTypeToString(vt) << std::endl;

	//parse input params
	 const i3d::Vector3d<int> pos(atoi(argv[2]),atoi(argv[3]),atoi(argv[4]));
	 const i3d::Vector3d<int> dir(atoi(argv[5]),atoi(argv[6]),atoi(argv[7]));
	 const int lStep=atoi(argv[8]);
	 const int rStep=atoi(argv[9]);
	 bool printAdvice=false;

    switch (vt)
    {
    case i3d::Gray8Voxel:
        {
            i3d::Image3d <i3d::GRAY8>img(argv[1]);
				printAdvice=PrintLine(img,pos,dir,lStep,rStep);
        }
        break;
    case i3d::Gray16Voxel:
        {
            i3d::Image3d <i3d::GRAY16>img(argv[1]);
				printAdvice=PrintLine(img,pos,dir,lStep,rStep);
        }
        break;
    case i3d::FloatVoxel:
        {
            i3d::Image3d <float>img(argv[1]);
				printAdvice=PrintLine(img,pos,dir,lStep,rStep);
        }
        break;
    case i3d::RGBVoxel:
        {
            i3d::Image3d <i3d::RGB>img(argv[1]);
				printAdvice=PrintLine(img,pos,dir,lStep,rStep);
        }
        break;
    case i3d::RGB16Voxel:
        {
            i3d::Image3d <i3d::RGB16>img(argv[1]);
				printAdvice=PrintLine(img,pos,dir,lStep,rStep);
        }
        break;
    default:
        std::cerr << "Other voxel types not supported" << std::endl;
    }

	 if (printAdvice) {
	 	cout << "\n# plot values as a function of x,y coordinates:\n";
		cout << "# splot \"data.dat\" u 1:2:5 t \"" << argv[1] << ": dir=" << dir << "\"\n";
	 	cout << "#\n# plot values as a function of x,y,z coordinates:\n";
		cout << "# TBA\n";
		cout << "#\n# plot values as a function of offset at the line:\n"; 
		cout << "# plot \"data.dat\" u 4:5 t \"" << argv[1] << ": dir=" << dir << "\"\n";
	 }


    return 0;
}
