#pragma once

#include <stdio.h>
#include <string.h>
#include <cxcore.h>
#include <cv.h>
#include <highgui.h>

#define PROCESS_LIST		"ProcList.txt"
#define GLOBAL_LOG			"global_log.txt"
#define LOCAL_LOG			"analysis_log.csv"
#define BASE_PATH			"D:\\usr\\work\\舌data"
#define MINIMACBETH			"MiniMacbeth.jpg"
#define CAMERA_FILE			"snapshot%d.jpg"
#define MAX_PATH_LEN		1024	// ファイルパス文字列の最大長
#define LOG_STRING			2048	// ログ文字列の長さ
#define DATE_STRING			64		// 日付文字列の長さ
#define SEARCH_AREA			200		// マクベスを探索するコーナー領域のサイズ
#define ROTATE_RESOLUTION	2.0		// マクベスを回転探索する角度刻み（度）
#define PATCH_SIZE			3		// パッチの色を平均する領域サイズ
#define NUM_MACBETH			2		// ミニマクベスの数
#define NUM_PATCH			9		// マクベス内パッチ数
#define COLOR				3		// 色チャネル数
#define SSIZE				7		// r,g,b の2次の重回帰推定行列のサイズ
#define SHOW_WIDTH			400		// 表示画像の幅
#define DISP1				"解析結果1"
#define DISP2				"解析結果2"
#define DISP3				"解析結果3"
//#define DEBUG_STOP_FRAME	3		// 処理中断するフレーム数（デバッグ）

// ミニマクベス画像 MiniMacbeth0.jpg から計算
// 中心パッチ座標 39,39 黒パッチ座標 20,45 (-19,+6)
#define BLACK_ANGLE 160.0 // =atan(+6/-19) (degree)
#define BLACK_LEN   19.5  // =sqrt((+6)^2 + (-19)^2)

// マクロ
#define SPRLOG sprintf_s(m_logString, LOG_STRING,

#ifdef _CONSOLE
#define ERROR_RET(msg) {			\
SPRLOG "%s", msg);					\
getchar();							\
return false;	}
#else
#define ERROR_RET(msg) {			\
SPRLOG "%s", msg);					\
return false;	}
#endif // _CONSOLE

void OnMouse1(int ev, int x, int y, int flags, void* param);

struct Param
{
	char dateStr[DATE_STRING];
	int  timeMDE;
	int  subject;
	int  count;
	Param() { *dateStr = '\0'; timeMDE = subject = count = 0; }
};

class Analysis
{
private:
	IplImage *m_macbeth;
	IplImage *m_camera;
	IplImage *m_show;
	FILE	 *m_log;
	FILE	 *m_gLog;
	Param	 *m_param;
	CvMat    *m_bMat;
	int      m_numParam;
	char	 m_filePath[MAX_PATH_LEN];
	char	 m_refPath[MAX_PATH_LEN];
	char	 m_logString[LOG_STRING];
	int		 m_numFrames;
	CvPoint  m_patchPos[NUM_PATCH * NUM_MACBETH];
	CvScalar m_mean    [NUM_PATCH * NUM_MACBETH];
	CvScalar m_stdev   [NUM_PATCH * NUM_MACBETH];
	CvScalar m_meanRef [NUM_PATCH * NUM_MACBETH];
	CvScalar m_stdevRef[NUM_PATCH * NUM_MACBETH];
	CvScalar *m_miniPatch[NUM_PATCH];
	CvScalar m_miniPatchRef[NUM_PATCH];
	float    m_showScale[3];

public:
	Analysis(void);
	~Analysis(void);
	bool Process();
	void OnMouse(int disp, int ev, int x, int y, int flags);

private:
	bool Init();
	bool ReadImage(int frame, bool ref = false);
	bool OpenLogFile(bool gLog = false, bool ref = false);
	bool CloseLogFile(bool gLog = false);
	bool SetPath(const char *dateStr, int timeMDE, int subject, int count);
	bool GetNumFrames();
	bool GetPatchPosition(bool ref = false);
	bool GetAllPatchColor(bool ref = false);
	bool GetPatchColor(int frame, bool ref = false);
	bool ShowImage(char *window = DISP1);
	bool WriteLog(bool gLog = false, bool fileOnly = false);
	bool CorrectionMat();
	double GetMRVal(int patch, int frame, int index);
	double GetMRVal2(double v0, double v1, double v2, int index);
	char ClipValue(double val);
};
