#pragma once

class CData3DObject;
// 0
// 创建时会修改传入数据，0.OK.  -2 Dog Err. -3 Calib Err.
class CTwoEyeApiObject
{
public:

	// nType = 0, double, multi_cpu,
	// nType = 1, float, multi_cpu + gpu;
	// nType = 2, float, single_cpu + gpu;
	virtual CData3DObject* Reconstruct3D(IplImage* limgp, IplImage* rimgp, const float& fFiltProp = 0.3, const float& fMinDistVal = 0.1, const int& nType = 0, const float& fNeighborPhase = 0.8) = 0;

	virtual bool ComputeOpticPlan(POINT3D* Pts, int szPts, double* OPlan, double* minErr, double* maxErr) = 0;

	// return internal buffer, don't release it.
	virtual IplImage* GetRectifyImage(char* lpszImgBuf, bool bLeft) = 0;

	// 获取 GetRectifyImage 函数相关矩阵的引用（不得单独释放和删除，在本对象释放后无效）
	virtual void GetRectifyImageRefMat(CvMat** pplmapx, CvMat** pplmapy, CvMat** pprmapx, CvMat** pprmapy) = 0;

	virtual void GetRectifyPoints(CvPoint2D32f* pSubpixs, int szPts, bool bLeft) = 0;

	virtual POINT3D Get3DColorPoint(const float& x1, const float& x2, const float& y) = 0;

	//
	virtual void ReleaseObject() = 0;

	// return 0 OK, -1 Dog Err;
	virtual int GetDogInfo(char* pszBuf) = 0;
	
protected:
	virtual ~CTwoEyeApiObject(){};
};

// 1
class COneEyeApiObject
{
public:

	virtual POINT3D Get3DColorPoint(const float& x, const float& y, double* OpticPlan) = 0;
	virtual void ConvertToLaserZ(POINT3D* Pts, int szPts, double* OpticPlan) = 0;
	virtual void ConvertToLaserZWithGlass(POINT3D* Pts, int szPts, double* OpticPlan, double fGlassThickness, double fRefractivity) = 0;

	//
	virtual void ReleaseObject() = 0;

	// return 0 OK, -1 Dog Err;
	virtual int GetDogInfo(char* pszBuf) = 0;
	
protected:
	virtual ~COneEyeApiObject(){};
};

// 2
class CStaticApiObject
{
public:

	virtual int CreateData3DObject(void** ppObj, POINT3D* pData, int width, int height, CvMat* cam, CvMat* dist) = 0;

	// nType = 0, double, cpu, multi thread, 4444
	// nType = 1, double, cpu, one thread, 4444
	// nType = 2, double, gpu, amp, 4444
	// nType = 3, float,  gpu, amp, 4444
	// nType = 103, float, gpu, amp, 44446
	// nType = 104, float gpu, amp, 4446
	virtual void ComputePhaseImage(IplImage* imgs[], IplImage* imgp, int nType, double jumptest = 0.4, double dbMinDistVal = 1.0) = 0;

	virtual int CalibrateTwoEyeUse2DPoints(char* cBufOfResult, IC_CAMERA_INFO* pInfo2, CvPoint2D32f* plPts, CvPoint2D32f* prPts, int nCount, int nType) = 0;

	// nLevel >= 5, Memory need: 9(0.5G), 10(1.5G),11(6G),12(24G),   fHole 7.5-9.5, if fHole < 0, solid.
	// asc file format   x y z nx ny nz r g b\n  rgb(0-255)
	// method = 0 normal, 1 smooth well.
	virtual bool WrapCloudNormalToPly(LPCSTR lpszAsc, LPCSTR lpszPly, int nLevel, float fHole, bool bHasColor, float& fProgress, int method = 0) = 0;

	// nT < real size ,return false
	virtual bool CloudNormalResampleDown(float* pfsource, int nS, float* pftarget, int& nT, double voxel_size) = 0;

	// method = 0 has normal, 1 has normal, 2 no normal 3 no normal
	virtual bool FindFeatureMatch(float* pfsource, int nS, float* pftarget, int nT, double ptDist, double* pOutRT, int method) = 0;
	
	virtual int PCLRemoveSmallGroups(POINT3D* pPts, int szPts, double nMaxPtDistance, int nMinPointsCount) = 0;

	virtual bool ComputeGaussianSubPixPeak(uchar* pData, int szData, float& fx, float& minErr, float& maxErr) = 0;

	// ref: uchar threshold = 250, 	int maxWidthHeight = 200, 	int minWidthHeight = 10, 	float minWHProp = 0.25, float fileAireProp = 0.8
    // szPts: nums of Subpix
	// return Subpix nums. 
	virtual int FindSimpleMark(CvPoint2D32f* pSubpixs, int szPts, IplImage* pImgSrc, uchar threshold, int maxWidthHeight, int minWidthHeight, float minWHProp, float fillAireProp) = 0;
	virtual int FindCircleCodeMark(CODE_POINT* pSubpixs, int szPts, IplImage* pImgSrc, int maxWidthHeight, int minWidthHeight, float minWHProp) = 0;

	virtual int FindNormalMark(CvPoint2D32f* pSubpixs, int szPts, IplImage* pImgSrc, int MaxCircleFitErr, int MinCirclePixRadius, int MaxCirclePixRadius, int MaxInOutProp, int MaxInOutContrast) = 0;

	// pGpts global data.  pSpts local data.
	// ref : distErr = 0.3f, minMatch = 4, maxMatch = 6
	virtual bool FindMatchOf3DMark(CODE_POINT* pGpts, int szGpts, CODE_POINT* pSpts, int szSpts, const float& distErr, const int& minMatch, const int& maxMatch) = 0;

	virtual bool GetRTOfMatchedCodedPoints(CODE_POINT* pGpts, int szGpts, CODE_POINT* pSpts, int szSpts, double* pRT) = 0;
	
	virtual bool ComputeFixedPoint(double* pRTs, int cnRTs, CODE_POINT& pen, float& fMinErr, float& fMaxErr) = 0;

	// cam 9, dist 4
	virtual CvPoint2D32f Project3D2Image(const CvPoint3D32f& cvpt, double* cam, double* dist) = 0;


	// return, 0 OK, -1 dll err, -2 gpu err.
	// example: nVerMajor.nVerMinor = 2.0,  nMemSize = 2048 (M)
	virtual int Init_Icp_gpu(int devid, int& nVerMajor, int& nVerMinor, int& nMemSize) = 0;

	// test.
	virtual int Test_FaceFind4Points(IplImage* pImg, IplImage* pImgColor, PT3D20* pts, int width, int height, CvPoint* pts4) = 0;

	// device info apis
	// iDog = -1,default;  0,1,2,3... (dog idx, not icdevice)
	virtual void SaveQR2File(LPCSTR lpszBmp, int iDog = -1) = 0;
	virtual bool GetDevConfigInfo(int& nFirstID, int& nSecondID, int& nLanguage, int& nCountry, int& nThirdid, int iDog = -1) = 0;
	virtual void SetDevRunInfo(int nAdjustZY, char cDevCount, int nStartScan, int nImageOK, int n3DataOK, float fTemperature, char cDevType = 5, char cStartStatus = 100) = 0;

	//
	virtual void ReleaseObject() = 0;

	// return 0 OK, -1 Dog Err, -6 no multi dog
	// iDog = -1,default;  0,1,2,3... (dog idx, not icdevice)
	virtual int GetDogInfo(char* pszBuf, int iDog = -1) = 0;

	// idxs = new int(127),  icdevice id
	// return dog nums.
	virtual int GetMultiDogIdx(int* idxs) = 0;
	
protected:
	virtual ~CStaticApiObject(){};
};

// 3
class CData3DObject
{
public:
	// 删除边界，fMaxProp = 3.0 - 6.0
	virtual int DeleteBorder(float fMeanPointDist, float fDistProp) = 0;

	// 删除碎片，测试 fMaxProp = 6.0， cMinPiece = 10000，返回值 < 255
	virtual int DeleteSmallPieces(const float& fMaxProp, const int& cMinPiece) = 0;

	// 单位 0.001mm
	virtual BOOL GetDepth(int* pDetph, char* pColor, int& nWidth, int& nHeight) = 0;
	virtual void GetFirstImage(IplImage* lpImage[], const int& nCount = 2) = 0; // no need delete, can't save to file
	virtual void SetFirstImage(IplImage* lpImage[], const int& nCount) = 0;  // can't delete lpImage; 

	// if NULL, no operate.
	virtual void SetRT(double* pTotalRT, double* pChangeRT, double* pSourceRT) = 0;
	virtual void GetRT(double* pTotalRT, double* pChangeRT, double* pSourceRT) = 0;
	virtual void GenerateTotalRT() = 0;
	
	// if pPts = NULL, return width,height.
	virtual BOOL CopyTo(PT3D20* pPts, int& width, int& height) = 0;
	virtual BOOL CopyFrom(PT3D20* pPts, int& width, int& height) = 0;
	virtual void FeatureToColor() = 0;
	virtual void Resample(const float& fProp) = 0;
	virtual void ComputeNormal(CData3DObject* pObj) = 0;
	virtual CData3DObject* Clone() = 0;
	virtual BOOL ResampleDown() = 0;

	//icp gpu NVIDIA
	virtual BOOL IcpTo(CData3DObject* pObj, BOOL bInMarkMode, float fWorkDist, float fMeanPointDist, int* ItersOfIcp4) = 0;
	virtual BOOL IcpTo(CvPoint3D32f* pt_ns, int nSize, float fWorkDist, float fMeanPointDist, int* ItersOfIcp4) = 0;

	virtual BOOL IcpTo(CvPoint3D32f* pt_ns, int nSize, float nSampleSize) = 0;

	// icp err compute
	virtual BOOL GetRTFitProp(CvPoint3D32f* pt_ns, int nSize, float fMeanPointDist, float fDistProp, int& nFitMe, int& nFitMeOut, int& nTotal) = 0;
	virtual BOOL GetRTFitProp(CData3DObject* pObj, float fMeanPointDist, float fDistProp, int& nFitMe, int& nFitMeOut, int& nTotal, BOOL bUseNormal = TRUE) = 0;
	virtual BOOL FindMatchPoint(const PT3D20& spt, PT3D20& mpt) = 0;

	virtual BOOL Save(LPCSTR lpszFileName) = 0;
	virtual BOOL Load(LPCSTR lpszFileName) = 0;

	virtual BOOL SaveAsAsc(LPCSTR lpszFileName, BOOL bClr) = 0;
	virtual BOOL SaveAsAC(LPCSTR lpszFileName) = 0;
	virtual BOOL SaveAsPIF(LPCSTR lpszFileName) = 0;

	// in memory, can't save to file，  trucMulti = 2.56 (2-6)
	virtual void CreateBox(double mmdist, double trucMulti) = 0;         //if had, delete it.
	virtual BOOL Integrate(CData3DObject* pObj) = 0;
	virtual BOOL SaveAsSTL(LPCSTR lpszFileName, float& fProgress) = 0;
	virtual BOOL SaveAsOBJ(LPCSTR lpszFileName, float& fProgress) = 0;
	virtual BOOL SaveAsAscNormal(LPCSTR lpszFileName, float& fProgress) = 0;
	
	// in memory, can't save to file,  pt_ns the same as GetRTFitProp(CvPoint3D32f* pt_ns,...
	virtual void CreateBoxColor(CvPoint3D32f* pt_ns, int nSize, int nRcdCnt = 16) = 0;    //if had, delete it.
	virtual BOOL AddColorItem(CData3DObject* pObj, float fmaxdist) = 0;
	virtual BOOL ComputeBoxColor(float& fProgress) = 0;
	virtual BOOL GetColorResult(int* colors, int mode) = 0;  // mode 0. source  1. bright  2. auto

	//
	virtual void ReleaseObject() = 0;
	
protected:
	virtual ~CData3DObject(){};
};

typedef void ON_SCANNER_PROJECT_OK(void* pCtnt);
typedef void ON_SCANNER_DATA_OK(void* pObj, void* pCtnt);
typedef void ON_SCANNER_IMAGE_OK(PUCHAR pImgData, int width, int height, BOOL bLeft, void* pCtnt);

typedef ON_SCANNER_PROJECT_OK *PON_SCANNER_PROJECT_OK;
typedef ON_SCANNER_DATA_OK *PON_SCANNER_DATA_OK;
typedef ON_SCANNER_IMAGE_OK *PON_SCANNER_IMAGE_OK;

struct XH_SCANNER_PARAMS
{
	int m_nPrjectMethod;                // 1
	int m_nCameraInRowMode;             // 0,1
	int m_nProjectorInRowMode;          // 0,1

	int m_lPrjWidth;                    // > 2000 or > 1280
	int m_prjResSel;                    // 9
	int m_prjTimes;                     // 3

	int m_nInitGlobalGain;              // 10
	int m_iInitExpTime;                 // 0,1,2

	double m_dbExpTime[3];              // 16.6, 33.3, 50

	int m_nCameraColorMode;             // 0,1
	int m_nHardwareDevType;             // 0,1,2
	int m_nDistenceFiltProp;            // 25
	int m_nMinProcessPixVal;            // 10

	int m_nLeftCameraUserID;            // 1001

	PON_SCANNER_PROJECT_OK m_pProjectOK;
	void*               m_pProjectContent;

	PON_SCANNER_DATA_OK m_pDataOK;
	void*               m_pDataContent;

	PON_SCANNER_IMAGE_OK m_pImageOK;
	void*               m_pImageContent;

};

typedef struct tagLASER_BODY_DATA
{
	int nLines;
	int nSize;
	CODE_POINT* pData;
}LASER_BODY_DATA, *PLASER_BODY_DATA;

typedef struct tagXH_SCANNER_DEV_INFO
{
	DWORD dogID;
	LONG  iCam;
	char  dev_sn[24];
	char  reserved[128];
	char  calib[2048];
}XH_SCANNER_DEV_INFO, *PXH_SCANNER_DEV_INFO;

// 4
// create err. -2:dog err. -3:can't find device. -4:can't start device.

class CScanner3DObject
{
public:

	// nErrCode = -1, calib err;  nErrCode = -2, device err;
	virtual BOOL AsynScan(int& nErrCode) = 0;

	// 1 white, 2 cross, 3 black
	virtual BOOL ProjectBack(int mode) = 0;

	virtual BOOL Pause(BOOL bPause) = 0;

	virtual BOOL AdjImgZY(const LONG& val, LONG& newVal) = 0;
	virtual BOOL AdjImgExpTime(const LONG& val, double& newVal) = 0;
	virtual BOOL AdjImgExpTimeMini(const LONG& val, double& newVal) = 0;

	virtual BOOL SaveCalib(void* plBuf, void* prBuf) = 0;
	
	//
	virtual void ReleaseObject() = 0;

	// return 0 OK, -1 Dog Err; ///// need 3k buffer, after 256 bytes, PXH_SCANNER_DEV_INFO at &pszBuf[256]
	virtual int GetDogInfo(char* pszBuf) = 0;

protected:
	virtual ~CScanner3DObject(){};
};

// 5
class CElectricCakeObject
{
public:

	virtual void Calibrate(CvPoint3D64f* p3Pts, CvPoint3D64f& center, CvPoint3D64f& axis) = 0;

	virtual BOOL Find(ULONG devId) = 0;
	virtual BOOL LoadCalib() = 0;
	virtual BOOL SaveCalib() = 0;

	// rotate usTimes * 1.8 deg.
	// cTimeout = 60 s.
	virtual BOOL Rotate(USHORT usTimes, BOOL bClockwise, int cTimeout) = 0;
	virtual BOOL Flip(USHORT usTimes, BOOL bLeft, int cTimeout) = 0;

	
	// pRT , 3*4 double. need calibration info.
	virtual BOOL GetCurrentRT(double* pRT) = 0;
	virtual float GetCurrentDeg() = 0;

	//
	virtual void ReleaseObject() = 0;

protected:
	virtual ~CElectricCakeObject(){};
};

// 6
class CCalibrationObject
{
public:

	virtual BOOL LoadBoard(LPCSTR lpszFileName) = 0;

	// pPts must have 30*30 (CvPoint2D32f), nCount >= 30*30
	// nCount will return the real count.
	// nSearchWH = 10
	virtual BOOL FindBoard(IplImage* img, CvPoint2D32f* pPts, int& nCount, int nSearchWH, BOOL bRefine, BOOL bLeft) = 0;

	// add left and right once.
	// if nCurFindAfterAdd == -1, clear all inner saved.
	// nCurFindAfterAdd will return groups of inner saved.
	// plPts = NULL, prPts = NULL, if not use.   normally, ImgWidth = 1280,  ImgHeight = 1024, depend on camera
	virtual BOOL AddCurFind(int& nCurFindAfterAdd, CvPoint2D32f* plPts, CvPoint2D32f* prPts, const int& nCount, const int& ImgWidth, const int& ImgHeight) = 0;

	// return the size of result, 
	// cBufOfResult will  set to 5k. 
	// more details: 
	// 0. desktop : (1) w*h  
	// 1. while-hand : old method, will not use
	// 2. laserline-hand : (1) w*h  (2) (w/2)*(h/2) 采样 (3) (w/4)*(h/4) 采样，采样
	// 3. infrared-hand : （1）1280*1024 （2）640*512 采样 （3）640*512 中心 （4）320*256 采样、采样 （5）320*256 中心、采样
	// 4. oral : （1）1280*1024 （2）640*512 采样 （3）512*640 中心 （4）256*320 中心、采样
	// nType = 0, desktop, 1, while-hand, 2, laserline-hand, 3, infrared-hand  4，oral
	virtual int Calibrate(char* cBufOfResult, int nType = 0) = 0;

	//
	virtual void ReleaseObject() = 0;

	// return 0 OK, -1 Dog Err;
	virtual int GetDogInfo(char* pszBuf) = 0;

protected:
	virtual ~CCalibrationObject(){};
};

// 7  ,  return -1 can't find server.

class CBodyServerObject
{
public:

	virtual BOOL DumpXhsFileAsAsc(LPCSTR lpszXhsPathName) = 0;

	virtual BOOL RefineBodyClouds(LPCSTR lpszBinBaseName, CvPoint3D32f* p3dPts, int* pSizes, int nGroups) = 0;

	virtual BOOL SendBodyToServer(CvPoint3D32f* p3dPts, int* pSizes, int nGroups) = 0;

	virtual void SetUserInfo(char* pBuf, int nSize) = 0;

	//
	virtual void ReleaseObject() = 0;

	// return 0 OK, -1 Dog Err;
	virtual int GetDogInfo(char* pszBuf) = 0;

protected:
	virtual ~CBodyServerObject(){};
};

// 8, 0 ok, -2 dog err.
class CGlobalRegistrationForMarkObject
{
public:

	// return id
	virtual int AddItem(CODE_POINT* cpts, const int& nNums, CvMat* matRT) = 0;
	virtual void AddItem(int from, int to, CODE_POINT* cptsFrom, CODE_POINT* cptsTo, int nCount) = 0;

	// 
	virtual void Analize(double dbDistAllow, int nMinPublic, double dbDistErr, int nMinMatch, int nMaxMatch, float& fProgress) = 0;

	virtual void Run(const int& iters, float* pCurIter) = 0;

	virtual bool GetResult(const int& id, double* dbRT) = 0;
	
	//
	virtual void ReleaseObject() = 0;
	
protected:
	virtual ~CGlobalRegistrationForMarkObject(){};
};

typedef struct tagFUSION_PARAM
{
	float fx;          // 574.0528
	float fy;          // 574.0528
	float cx;          // -1
	float cy;          // -1
	int   width;       // 640
	int   height;      // 480
	float fprop;       // 比例，标准为3m*3m*3m
	float fdist;       // 设备 与 中心 距离
	int   color;       // 色彩使用：0，全部不使用；1 快速扫描中不使用，融合后使用；2 快速扫描中使用，融合后不使用；3 都使用；
	float mmdist;      // 细节度调整参数，默认0.03m，应大于0.012
	char  sdir[256];   // 工作目录

}FUSION_PARAM, *PFUSION_PARAM;

// 9， 
class CHandScanObject
{
public:

	// return 0,OK,   -1,No Dog.
	virtual int Start(int nTimes) = 0;

	// pDepth 16bit ushort
	// pColor 24bit rgb
	// 0 OK(init), 1 lost, 2 auto jump, 3 integrate, 4 normal:  no shift, no integrate, 
	// pRT ,if NULL,use icp; else use it.
	// iJump == 0, no jump; 1, force jump; 2 auto jump;     return. groups
	virtual int Go(void* pDepth, void* pColor, double* pRT, int& iJump) = 0;

	// force jump.
	virtual int GoS(void* pDepth, void* pColor, double* pRT, CvPoint3D32f* pTarget) = 0;

	virtual void GetImage(void* pColor) = 0;

	// just return;
	virtual void Stop(int& iJumps, float& fProgress) = 0;

	// nTimes = ReGo.nTimes , fProgress < 1.0，color_mode 0 原始 1 超亮，2 自动
	virtual void FixColor(int nTimes, float& fProgress, int color_mode) = 0;

	virtual void ReleaseObject() = 0;

	// return 0 OK, -1 Dog Err;
	virtual int GetDogInfo(char* pszBuf) = 0;

protected:
	virtual ~CHandScanObject(){};
};

// 10, 0 ok, -2 dog err.
class CMeshProObject
{
public:

	struct XH_HOLE_INFOS
	{
		float cx, cy, cz;
		unsigned int edges;
		double diagonal;
		double boundaryLength;
	};

	virtual BOOL Load(LPCSTR lpszFileName) = 0;
	virtual BOOL Save(LPCSTR lpszFileName, int bBinary) = 0; // 0 asc 1 binary 2 auto

	virtual void Smooth(int iterations) = 0;
	virtual unsigned int FindAllHoles() = 0;
	virtual BOOL GetHoleInfo(unsigned int idx, XH_HOLE_INFOS& info) = 0;
	virtual BOOL GetHoleVertex(const unsigned int _index, float* pVertex3D, unsigned int& nCount) = 0; // nCount * 3
	virtual BOOL FillHole(unsigned int idx) = 0;
	virtual int Simple(float prop) = 0;	

	virtual void ReleaseObject() = 0;

protected:
	virtual ~CMeshProObject(){};
};


// 11, 0 ok, -2 dog err.
class CMultiCameraObject
{
public:

	// first.
	virtual int AddCameraPos(CvMat* matRT, bool bFixed) = 0;

	// second
	virtual int AddObject3DPoint(const CvPoint3D64f& xyz, bool bFixed = false) = 0;

	// need 
	virtual int AddCameraParam(CvMat* cam, CvMat* dist) = 0;

	// setup.
	virtual bool AddImagePoint2D(const CvPoint2D64f& xy, const int& id_3d, const int& id_pos, const int& pid_cam) = 0;

	virtual void Run(const int& iters, float* pCurIter) = 0;

	virtual bool GetCameraPos(int id_pos, double* pdbRT) = 0;
	virtual bool GetObject3DPoint(int id_3d, CvPoint3D64f& xyz) = 0;

	//
	virtual void ReleaseObject() = 0;

protected:
	virtual ~CMultiCameraObject() {};
};