/***************************************************************************
 *   Copyright (C) 2006 by Miguel Armando Riem de Oliveira   *
 *   mike@BlackBandit   *
 *                                                                         *
 *   This program 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 2 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 this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

//guardar parametros e carregar settings da camara


#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

//standard includes
#include <stdio.h>
#include <stdlib.h>
#include <iostream.h>
#include <string.h>

//opencv includes
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
#include <cvaux.h>

//libraw libdc includes
#include <dc1394_control.h>
#include <raw1394.h>

//conversions lib include
#include <conversions.h>

//myincludes
#include <timer.h>

//my defines
#define TRUE 1
#define FALSE 0

#define AUTO 1
#define MANUAL 0


//predefined camera params
#define SET1_BRIGHTNESS 350
#define SET1_EXPOSURE 500
#define SET1_SHARPNESS 70
#define SET1_SATURATION 130
#define SET1_GAMMA 1
#define SET1_SHUTTER 7
#define SET1_GAIN 60

#define SET2_BRIGHTNESS 380
#define SET2_EXPOSURE 500
#define SET2_SHARPNESS 70
#define SET2_SATURATION 130
#define SET2_GAMMA 0
#define SET2_SHUTTER 7
#define SET2_GAIN 235
//BUGS
//for some reason if two independent classes are declared and different frame rates are set, the frame rate of both cameras is the smallest selected frame rate. 



class camera1394_control {
public:

	
	/**
	 * @brief Class constructor
	 */
	camera1394_control();
	

	/**
	 * @brief Overloaded class constructor
	 * @param HN Handle number
	 * @param NN Node number
	 * @param CF Color format. Check int SetColorFormat(int cm) for more info.
 	 * @param FR Frame rate. Check int SetFrameRate(int fr) for more info.
	 */
	camera1394_control(int HN, int NN, int CF, int FR);	
	
	 /**
	 * @brief Class destructor
	 */
	~camera1394_control();

	//reports
	/**
	 * @brief Prints to shell all the camera possible modes
	 * @return function result. 1 is OK 0 is NOK
	 */
	int PrintPossibleModes(void);

	/**
	 * @brief Prints to shell all the camera possible frame rates
	 * @return function result. 1 is OK 0 is NOK
	 */
	int PrintPossibleFrameRates(void);
	
	/**
	 * @brief Prints to shell all the camera features
	 * @return function result. 1 is OK 0 is NOK
	 */
	int PrintCameraFeatures(void){dc1394_print_feature_set(featureset); return 1;};

	/**
	 * @brief Prints to shell some camera info
	 * @return function result. 1 is OK 0 is NOK
	 */
	int PrintCameraInfo(void){dc1394_print_camera_info(camerainfo); return 1;};

	//flags sets
	/**
	 * @brief Sets the flag HandleNum to num
	 * @param num Number of the handle
	 * @return function result. 1 is OK 0 is NOK
	 */
	int SetHandleNum(int num){handlenum=num;;return 1;};

	/**
	 * @brief Sets the flag NodeNum to num
	 * @param num Number of the node
	 * @return function result. 1 is OK 0 is NOK
	 */
	int SetNodeNum(int num){nodenum=num;return 1;};
	
	/**
	 * @brief Sets the camera color format
	 * 
	 * The color format is defined in an enum declared in dc1394_control.h \n
	 * The supported modes are:\n
		- MODE_160x120_YUV444 = 64 (WARNING: TESTS FAILED WITH THIS OPTION)
		- MODE_320x240_YUV422
		- MODE_640x480_YUV411
		- MODE_640x480_YUV422 (WARNING: TESTS FAILED WITH THIS OPTION)
		- MODE_640x480_RGB (WARNING: TESTS FAILED WITH THIS OPTION)
		- MODE_640x480_MONO (WARNING: TESTS FAILED WITH THIS OPTION)
		- MODE_640x480_MONO16 (WARNING: TESTS FAILED WITH THIS OPTION)
	 *
	 * If none of this modes is selected the default mode MODE_320x240_YUV422 is selected \n
	 * @param cm Color format reference given by an enum defined in dc1394_control.h
	 * @return function result. 1 is OK 0 is NOK
	 */
	int SetColorFormat(int cm);

	/**
	 * @brief Sets a camera feature to manual or auto control
	 *
	 * The available features are defined in a enum of dc1394_control.h \n
	 * These are: \n
		- FEATURE_BRIGHTNESS = 416
		- FEATURE_EXPOSURE
		- FEATURE_SHARPNESS
		- FEATURE_WHITE_BALANCE
		- FEATURE_HUE
		- FEATURE_SATURATION
		- FEATURE_GAMMA
		- FEATURE_SHUTTER
		- FEATURE_GAIN
		- FEATURE_IRIS
		- FEATURE_FOCUS
		- FEATURE_TEMPERATURE
		- FEATURE_TRIGGER
		- FEATURE_TRIGGER_DELAY
		- FEATURE_WHITE_SHADING
		- FEATURE_FRAME_RATE
	 * @param f feature to change
	 * @param val 1 is auto and 0 for manual
	 * @return function result. 1 is OK 0 is NOK
	 */
	int SetFeatureToManualAuto(unsigned int f, unsigned int val);
	

	int SetPredefinedParams(int paramsset);
	
	/**
	 * @brief Sets the flag verbose to val.
	 *
	 * If true reports will be written to the shell.
	 * @param val 1 for TRUE or 0 for FALSE
	 * @return function result. 1 is OK 0 is NOK
	 */
	int SetFlgverbose(unsigned char val){return flg.verbose=val;};
		
	/**
	 * @brief Sets the flag testimgparams to val. 
	 *
	 *If true every time a get image is called the pointer to the image is first tested avoiding a runtime crash.
	 * @param val 1 for TRUE or 0 for FALSE
	 * @return function result. 1 is OK 0 is NOK
	 */
	int SetFlgtestimgparams(unsigned char val){return flg.testimgparams=val;};


	//utils
	int DmaUnlisten(void){return dc1394_dma_unlisten(handle,&cameracapture);};
	int CleanupIsoChannels(void){/*dc1394_cleanup_iso_channels_and_bandwidth();*/return 1;};

	/**
	 * @brief Opens the raw1394 handle with the num HandleNum
	 * @return function result. 1 is OK 0 is NOK
	 */
	int OpenHandle(void);
	
	/**
	 * @brief Turns off the camera in handle handlenum and node nodenum
	 * @return function result. 1 is OK 0 is NOK
	 */
	int TurnOffCamera(void);
	
	/**
	 * @brief Turns on the camera in handle handlenum and node nodenum
	 * @return function result. 1 is OK 0 is NOK
	 */
	int TurnOnCamera(void);

	/**
	 * @brief Gets all the cameras and their nodes in the predefined handlenum
	 * @return function result. 1 is OK 0 is NOK
	 */
	int GetCameraNodes(void);

	/**
	 * @brief Sets up the capture
	 * @return function result. 1 is OK 0 is NOK
	 */
	int SetupCapture_dma(void);

	/**
	 * @brief Starts iso transmission
	 * @return function result. 1 is OK 0 is NOK
	 */
	int StartIsoTransmission(void);

	/**
	 * @brief Gets an image from the camera at handle handlenum and node nodenum
	 *
	 * The img data will be filled with the captured frame information. If testimgparams flag is set (it's set by default) the function first checks if the img properties are the same as the capture ones avoiding a runtime crash. Of course this test will take a bit longer if performed.
	 * @param img Pointer to the user image.
	 * @return function return the value of the current framerate stored in captureparams.FrameRate
	 */
	int GetFrame_dma(IplImage *img);

	/**
	 * @brief Inits camera to its factory settings
	 * @return function result. 1 is OK 0 is NOK
	 */
	int InitCameraToFactorySettings(void){return dc1394_init_camera(handle, numnodes[nodenum]);};


	//gets

	int GetFrameRate(void);


	int GetBrightness(void);
	int GetSaturation(void);
	int GetExposure(void);
	int GetSharpness(void);
	int GetWhiteBalance(void);
	int GetHue(void);
	int GetGamma(void);
	int GetShutter(void);
	int GetGain(void);
	int GetIris(void);
	
	//sets
	int SetFrameRate(int fr);
	int SetBrightness(unsigned int b);
	int SetSaturation(unsigned int s);
	int SetExposure(unsigned int e);
	int SetSharpness(unsigned int s);
	int SetWhiteBalance(unsigned int ub, unsigned int vr);
	int SetHue(unsigned int h);
	int SetGamma(unsigned int g);
	int SetShutter(unsigned int s);
	int SetGain(unsigned int g);

// dc1394_get_iris(raw1394handle_t handle, nodeid_t node,
//                 unsigned int *iris);
// int dc1394_set_iris(raw1394handle_t handle, nodeid_t node, unsigned int iris);
// int dc1394_get_focus(raw1394handle_t handle, nodeid_t node,unsigned int *focus);
// int dc1394_set_focus(raw1394handle_t handle, nodeid_t node,unsigned int focus);
// int dc1394_get_temperature(raw1394handle_t handle, nodeid_t node,unsigned int *target_temperature,unsigned int *temperature);
// int dc1394_set_temperature(raw1394handle_t handle, nodeid_t node,unsigned int target_temperature);
// int dc1394_get_white_shading(raw1394handle_t handle, nodeid_t node, unsigned int *r_value, unsigned int *g_value,unsigned int *b_value);
// int dc1394_set_white_shading(raw1394handle_t handle, nodeid_t node,unsigned int r_value, unsigned int g_value, unsigned int b_value);
// int dc1394_get_trigger_delay(raw1394handle_t handle, nodeid_t node, unsigned int *trigger_delay);
// int dc1394_set_trigger_delay(raw1394handle_t handle, nodeid_t node, unsigned int trigger_delay);
// int dc1394_get_frame_rate(raw1394handle_t handle, nodeid_t node, unsigned int *frame_rate);
// int dc1394_set_frame_rate(raw1394handle_t handle, nodeid_t node, unsigned int frame_rate);
// int dc1394_get_hue(raw1394handle_t handle, nodeid_t node,unsigned int *hue);

private:
	raw1394handle_t handle;

	int handlenum;
	int nodenum;
	nodeid_t *numnodes;
	dc1394_feature_info *feature;
	dc1394_feature_set *featureset;
	dc1394_miscinfo *info;
	dc1394_camerainfo *camerainfo;
	int numCameras;
	dc1394_cameracapture cameracapture;
	char* devicename;
	unsigned char * TmpBuffer;	

	struct {unsigned char verbose;
		unsigned char hashandle;
		unsigned char testimgparams; //enabled by default. If you wish to disable you must be sure that the IplImage you give to GetFrame_dma has the correct properties
		}flg;
	
	struct {int width;
		int height;	
		int numchannels;
		int colormode;
		int framerate;
		unsigned int Brightness,Exposure,Sharpness,Hue,Saturation, Gamma, Temperature, Shutter, Gain ,FrameRate,Iris;
		struct {unsigned int u_b_value, v_r_value;}WhiteBalance;

		}captureparams;

	//reference to flg.verbose 
	//const unsigned char &vb=flg.verbose;
};
