#include "StdAfx.h"
#include "ImageUtility.h"

HINTERNET g_hOpen, g_hConnect;

/////////////////// WorkerFunction ////////////////////// 
DWORD WINAPI WorkerFunction(IN LPVOID vThreadParm)
	/*
	Purpose:
	Call InternetConnect to establish a FTP session  
	Arguments:
	vThreadParm - points to PARM passed to thread
	Returns:
	returns 0  
	*/
{
	//PARM* pThreadParm;
	// Initialize local pointer to void pointer passed to thread
	//pThreadParm = (PARM*)vThreadParm;

	FTP_INFO *ftpinfo = (FTP_INFO*)vThreadParm;

	if (ftpinfo == NULL)
		return 1;

	g_hConnect = 0;

	if ( !( g_hConnect = InternetConnect (
		g_hOpen, 
		ftpinfo->ConnectAddress,
		ftpinfo->ConnectPort,
		ftpinfo->Id,
		ftpinfo->Pw,
		INTERNET_SERVICE_FTP, 
		INTERNET_FLAG_PASSIVE,
		0 ) ) )
	{
		//cerr << "Error on InternetConnnect: " << GetLastError() << endl;
		
		return 1; // failure
	}

	return 0;  // success
}

CImageUtility::CImageUtility(void) : pFtpUploadThread(NULL), pFtpUploadThread_ing(NULL)
{
}


CImageUtility::~CImageUtility(void)
{
	if (pFtpUploadThread_ing)
	{
		if (WaitForSingleObject (pFtpUploadThread_ing->m_hThread, 2000) == WAIT_TIMEOUT)
		{
			AfxMessageBox(_T("Current File Upload Cancel"), MB_OK);
			return;
		}
	}
}

BOOL CImageUtility::FileRead(CString FilePath, uint32_t Width, uint32_t Height, void *mem, uint32_t TypeSize)
{
	FILE* fp;

	int errorno = 0;
	int FileLen = Width * Height;
	if((errorno = fopen_s(&fp,FilePath,"rb")))
	{
		AfxMessageBox("Read File Open Error 00");
		return FALSE;
	}
	fseek(fp,0L,SEEK_END);
	long len =ftell(fp);
	fseek(fp, len-FileLen*TypeSize, SEEK_SET);
	int ReadCount = fread(mem,TypeSize,FileLen,fp);
	if(ReadCount < FileLen)
	{
		AfxMessageBox("File Read error 00!");
		return FALSE;
	}

	fclose(fp);

	return TRUE;
}

UINT CImageUtility::FileRead_Thread ( LPVOID pParam )
{
	FTP_INFO *ftpinfo = (FTP_INFO*)pParam;

	if (ftpinfo == NULL)
		return 0;

	if( g_hConnect == NULL ) return 0;

	if( !FtpSetCurrentDirectory( g_hConnect, ftpinfo->DirPath ) )
	{
		AfxMessageBox(_T("FTP Path Error"));

		InternetCloseHandle( g_hConnect );
		InternetCloseHandle( g_hOpen );
		return 0;
	}
	
	if( !FtpPutFile( g_hConnect, ftpinfo->UploadFile, ftpinfo->UploadFile, INTERNET_FLAG_TRANSFER_BINARY|INTERNET_FLAG_RELOAD, 0 ))
	{
		AfxMessageBox(_T("FTP File Put Error"));

		InternetCloseHandle( g_hConnect );
		InternetCloseHandle( g_hOpen );
		return 0;
	}

	return 1;
}

void CImageUtility::FileUpload (FTP_INFO *ftpinfo)
{
	if (ftpinfo == NULL)
		return;	

CONNECT_RETRY:

	BOOL bRetry = FALSE;

	// FTP 오픈
	if( (g_hOpen = InternetOpen(NULL, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, NULL)) == NULL )
	{
		DWORD dwgle = GetLastError();
		CString strTempory;
		strTempory.Format(_T("Can't Use Network, Windows Code : 0x%08X"), dwgle);
		AfxMessageBox(strTempory);
		SAFE_DELETE(ftpinfo);
		return;
	}

	// FTP 서버 연결

	pFtpUploadThread = AfxBeginThread( (AFX_THREADPROC)WorkerFunction, ftpinfo, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
	pFtpUploadThread->m_bAutoDelete = FALSE;
	pFtpUploadThread->ResumeThread();

	if (!pFtpUploadThread)
	{
		AfxMessageBox(_T("Windows Thread Fail"));
		SAFE_DELETE(ftpinfo);
		return;
	}

	DWORD dwResult = WaitForSingleObject (pFtpUploadThread->m_hThread, 5000);

	// 쓰레드 타임아웃 (접속지연)
	if (dwResult == WAIT_TIMEOUT)
	{
		if ( g_hOpen )
		{
			InternetCloseHandle ( g_hOpen );
		}

		// 쓰레드가 TimeOut된 상황은 InternetCloseHandle로서 해제됨
		WaitForSingleObject (pFtpUploadThread->m_hThread, INFINITE);

		bRetry = TRUE;
	}

	// 쓰레드 완료 (접속 불가)
	if (dwResult == WAIT_OBJECT_0 && !g_hConnect)
	{
		if ( g_hOpen )
		{
			InternetCloseHandle ( g_hOpen );
		}

		bRetry = TRUE;
	}
	// 쓰레드 완료 (접속 성공)
	else if (dwResult == WAIT_OBJECT_0 && g_hConnect)
	{
		bRetry = FALSE;
	}

	delete pFtpUploadThread;
	pFtpUploadThread = NULL;

	// 접속 재시도 확인
	if (bRetry)
	{
		if (ftpinfo->CheckConnect)
		{
			SAFE_DELETE(ftpinfo);
			return;
		}

		if (AfxMessageBox(_T("FTP Connect Fail, Retry?"), MB_RETRYCANCEL) == IDRETRY)
		{
			goto CONNECT_RETRY;
		}
		else
		{
			SAFE_DELETE(ftpinfo);
			return;
		}
	}

	// FTP 업로드

	pFtpUploadThread_ing = AfxBeginThread( (AFX_THREADPROC)FileRead_Thread, ftpinfo, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
	pFtpUploadThread_ing->m_bAutoDelete = FALSE;
	pFtpUploadThread_ing->ResumeThread();

	if (pFtpUploadThread_ing)
	{
		DWORD dwResult = WaitForSingleObject (pFtpUploadThread_ing->m_hThread, 30000);

		if (dwResult == WAIT_TIMEOUT)
			AfxMessageBox(_T("Image Upload TimeOut (max 30sec)"));

		delete pFtpUploadThread_ing;
		pFtpUploadThread_ing = NULL;
	}

	if( g_hOpen ) 
	{
		InternetCloseHandle( g_hOpen );
		g_hOpen = NULL;
	}
	if( g_hConnect )
	{
		InternetCloseHandle( g_hConnect );
		g_hConnect = NULL;
	}

	SAFE_DELETE(ftpinfo);
}

BOOL CImageUtility::MakeImage (CString strRawFilePath, CString strOutFilePath, uint32_t Width, uint32_t Height, UINT Type/* = 14*/)
{
	CxImage img;

	// RAW 메모리 로드
	BYTE *pRaw = new BYTE[Width*Height*2];
	if (!FileRead(strRawFilePath,Width, Height,pRaw,sizeof(WORD)))
		return FALSE;
	
	WORD nMin = 0xFFFF;
	WORD nMax = 0;
	WORD nTemp;
	double dTemp;

	// min, max 탐색
	WORD *pWord = (WORD *)pRaw;
	for (UINT i=0; i<Width*Height; i++)
	{
		// 2Byte 리딩
		nTemp = pWord[i] >> (16 - Type);

		if( nTemp > nMax ) 
			nMax = nTemp;
		if( nTemp < nMin ) 
			nMin = nTemp;
	}

	// min, max를 통한 값 보정
	for (UINT i=0; i<Width*Height; i++)
	{
		// 2Byte 리딩
		nTemp = pWord[i]  >> (16 - Type);
		
		dTemp = (((double)nTemp - (double)nMin) / ((double)nMax - (double)nMin)) * 0xFF /*8bit*/;

		pWord[i] = (WORD)dTemp;
		//pRaw[i] = (BYTE)pWord[i];
		pRaw[i] = (BYTE)pWord[i] * -1;
	}
	
	if (!img.CreateFromArray(pRaw, Width, Height, 8, Width, TRUE))
	{
		delete [] pRaw;
		return FALSE;
	}

	if (!img.Save(strOutFilePath, CXIMAGE_FORMAT_PNG))
	{
		delete [] pRaw;
		return FALSE;
	}

	delete [] pRaw;
	return TRUE;
}

void CImageUtility::ResizeImage (CString strFilePath, uint32_t Width, uint32_t Height)
{
	CxImage img;

	img.Load(strFilePath);
	img.Resample(Width, Width);
	img.Save(strFilePath, CXIMAGE_FORMAT_PNG);
}