#include "stdafx.h"

#include <Jai_Factory.h>
#include <conio.h>
#include <time.h>
#include <dos.h>
#include <iostream>

using namespace std;

VIEW_HANDLE g_hView; // Global view handle
THRD_HANDLE     m_hThread;      // Acquisition Thread Handle
BOOL SaveImageToFile(J_tIMAGE_INFO* ptRawImageInfo, char*filename);
static void __stdcall StreamCBFunc(J_tIMAGE_INFO * pAqImageInfo);

char file1[] = "0001.tiff";
char file2[] = "0002.tiff";

bool imgAq=FALSE;
bool imgSeq;

//-------------------------------------------------------------------------------
// tictoc function
//-------------------------------------------------------------------------------

long tictoc(int stat)
{
	/*Declaração de variaveis*/
	long temp_ms, temp_us, temp, Final;

	static long Inicio;	

	SYSTEMTIME systemTime;
	GetSystemTime( &systemTime );

	FILETIME fileTime;
	SystemTimeToFileTime( &systemTime, &fileTime );

	ULARGE_INTEGER uli;
	uli.LowPart = fileTime.dwLowDateTime; // could use memcpy here!
	uli.HighPart = fileTime.dwHighDateTime;

	ULONGLONG systemTimeIn_ms( uli.QuadPart/10000 );

	//cout  << "System time in ms since 1 January 1601 (UTC): " << systemTimeIn_ms << '\n';
	
	if (stat==0) //é um tic
	{
		/*Para utilizar a funcao null utilizar #include <stdio.h> */
		Inicio=(long)systemTimeIn_ms;
		return 0;
	}
	else 
	{
		Final=(long)systemTimeIn_ms;
		temp_ms=(Final-Inicio);

		cout  << "Tempo decorrido (ms)" << temp_ms << '\n';

		return temp_ms;
	}
} 

//-------------------------------------------------------------------------------
// Call back sample function
//-------------------------------------------------------------------------------

static void __stdcall StreamCBFunc(J_tIMAGE_INFO * pAqImageInfo)
{
	// Shows image
	// J_Image_ShowImage(g_hView, pAqImageInfo);
	if (imgSeq==TRUE)
	{
		if(SaveImageToFile(pAqImageInfo, file1)==FALSE)
		{
			printf("Failed to save file to disk, file name: %s\n",file1);
			return;
		}
		printf("Gravou 1 \n");
	}
	else if (imgSeq==FALSE)
	{
		if(SaveImageToFile(pAqImageInfo, file2)==FALSE)
		{
			printf("Failed to save file to disk, file name: %s\n",file2);
			return;
		}
		printf("Gravou 2 \n");
	}
}


BOOL SaveImageToFile(J_tIMAGE_INFO* ptRawImageInfo, char*filename)
{
	imgAq=TRUE;
	J_tIMAGE_INFO tCnvImageInfo; // Image info structure
	// Allocate the buffer to hold converted the image
	if (J_Image_Malloc(ptRawImageInfo, &tCnvImageInfo) != J_ST_SUCCESS)
	return FALSE;
	// Convert the raw image to image format
	if (J_Image_FromRawToImage(ptRawImageInfo, &tCnvImageInfo) != J_ST_SUCCESS)
	return FALSE;
	//// Save the image to disk in BMP format
	//if (J_Image_SaveFileEx(&tCnvImageInfo, (LPCTSTR)filename, J_FF_JPEG) != J_ST_SUCCESS)
	//return FALSE;
	// Save the image to disk in TIFF format
	if (J_Image_SaveFile(&tCnvImageInfo,(LPCTSTR)filename) != J_ST_SUCCESS)
	return FALSE;
	// Free up the image buffer
	if (J_Image_Free(&tCnvImageInfo) != J_ST_SUCCESS)
	return FALSE;
	return TRUE;
}

//-------------------------------------------------------------------------------
// Live View sample function
//-------------------------------------------------------------------------------

//BOOL LiveView(CAM_HANDLE hCamera)
//{
//	THRD_HANDLE hThread;
//	//NODE_HANDLE hNode;
//	int64_t int64Val;
//	SIZE ViewSize = {100, 100};
//	POINT TopLeft = {0, 0};
//
//	// Get Width from the camera
//	if (J_Camera_GetValueInt64(hCamera, "Width", &int64Val) != J_ST_SUCCESS)
//	system ("pause");
//	return FALSE;
//
//	ViewSize.cx = (LONG)int64Val; // Set window size cx

//	// Get Height from the camera
//	if (J_Camera_GetValueInt64(hCamera, "Height", &int64Val) != J_ST_SUCCESS)
//	return FALSE;
//
//	ViewSize.cy = (LONG)int64Val; // Set window size cy
//	// Open view window
//	//if (J_Image_OpenViewWindow((LPCTSTR)"Live view!",&TopLeft,&ViewSize,&g_hView) != J_ST_SUCCESS)
//	//return FALSE;
//
//	// Open stream
//	void *vfptr = reinterpret_cast<void*>(StreamCBFunc);
//	J_IMG_CALLBACK_FUNCTION *cbfptr = reinterpret_cast<J_IMG_CALLBACK_FUNCTION*>(&vfptr);
//
//	if (J_Image_OpenStream(hCamera,0,NULL,*cbfptr,&hThread,ViewSize.cx*ViewSize.cy*6) != J_ST_SUCCESS)
//	return FALSE;
//	
//	// Acquisition Start
//	if (J_Camera_ExecuteCommand(hCamera, "AcquisitionStart") != J_ST_SUCCESS)
//	return FALSE;
//
//	// Message loop
//	//while (!_kbhit())
//	while (imgAq==FALSE)
//	{
//		MSG msg;
//		if (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
//		{
//			::TranslateMessage(&msg);
//			::DispatchMessage(&msg);
//		}
//	}
//	tictoc(0);
//	// Acquisition Stop
//	if (J_Camera_ExecuteCommand(hCamera, "AcquisitionStop") != J_ST_SUCCESS)
//	return FALSE;
//	 //Close stream
//	J_Image_CloseStream(hThread);
//	//// Close view window
//	//J_Image_CloseViewWindow(g_hView);
//	printf("tictoc:\n");
//	tictoc(1);
//
//	return TRUE;
//}

//-------------------------------------------------------------------------------
// _tmain
//-------------------------------------------------------------------------------

int _tmain(int argc, _TCHAR* argv[])
{
	
	//-------------------------------------------------------------------
	//Socktes comm
	//-------------------------------------------------------------------
	WORD wVersionRequested;
	WSADATA wsaData;
	int wsaerr;

	printf("Starting socket testing\n");

	// Using MAKEWORD macro, Winsock version request 2.2
	wVersionRequested = MAKEWORD(2, 2);
	wsaerr = WSAStartup(wVersionRequested, &wsaData);
	if (wsaerr != 0)
	{
		/* Tell the user that we could not find a usable */
		/* WinSock DLL.*/
		printf("\tThe Winsock dll not found!\n");
		return 0;
	}
	else
	{
		printf("\tThe Winsock dll found!\n");
		printf("\tThe status: %s.\n", wsaData.szSystemStatus);
	}

	/* Confirm that the WinSock DLL supports 2.2.*/
	/* Note that if the DLL supports versions greater    */
	/* than 2.2 in addition to 2.2, it will still return */
	/* 2.2 in wVersion since that is the version we      */
	/* requested.                                        */
	if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2 )
	{
		/* Tell the user that we could not find a usable */
		/* WinSock DLL.*/
		printf("\tThe dll do not support the Winsock version %u.%u!\n", LOBYTE(wsaData.wVersion),HIBYTE(wsaData.wVersion));
		WSACleanup();
		return 0;
	}
	else
	{
		printf("\tThe dll supports the Winsock version %u.%u!\n", LOBYTE(wsaData.wVersion),HIBYTE(wsaData.wVersion));
		printf("\tThe highest version this dll can support: %u.%u\n", LOBYTE(wsaData.wHighVersion), HIBYTE(wsaData.wHighVersion));
	}

	printf("Socket setup\n");
	//////////Create a socket////////////////////////
	//Create a SOCKET object called m_socket.
	SOCKET m_socket;

	// Call the socket function and return its value to the m_socket variable.
	// For this application, use the Internet address family, streaming sockets, and
	// the TCP/IP protocol.
	// using AF_INET family, TCP socket type and protocol of the AF_INET - IPv4
	m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	// Check for errors to ensure that the socket is a valid socket.
	if (m_socket == INVALID_SOCKET)
	{
		printf("\tError at socket(): %ld\n", WSAGetLastError());
		WSACleanup();
		return 0;
	}
	else
	{
		printf("\tSocket is OK!\n");
	}

	printf("Bind\n");
	////////////////bind()//////////////////////////////
	// Create a sockaddr_in object and set its values.
	sockaddr_in service;
	// AF_INET is the Internet address family.
	service.sin_family = AF_INET;
	// "127.0.0.1" is the local IP address to which the socket will be bound.
	service.sin_addr.s_addr = inet_addr("127.0.0.1");
	// 55555 is the port number to which the socket will be bound.
	service.sin_port = htons(55555);
	// Call the bind function, passing the created socket and the sockaddr_in structure as parameters.
	// Check for general errors.

	if (bind(m_socket, (SOCKADDR*)&service, sizeof(service)) == SOCKET_ERROR)
	{
		printf("\tbind() failed: %ld.\n", WSAGetLastError());
		closesocket(m_socket);
		return 0;
	}
	else
	{
	   printf("\tbind is OK!\n");
	}

	printf("Listen\n");
	// Call the listen function, passing the created socket and the maximum number of allowed
	// connections to accept as parameters. Check for general errors.

	if (listen(m_socket, 1) == SOCKET_ERROR)
		printf("\tlisten(): Error listening on socket %ld.\n", WSAGetLastError());
	else	
	{
		printf("\tWaiting for connections...\n");
	}

	//---------------------------------------------------------------------
	//JAI
	//---------------------------------------------------------------------
	
	printf("Starting JAY aquisition\n");

	FACTORY_HANDLE hFactory = NULL; // Factory Handle
	CAM_HANDLE hCamera = NULL; // Camera Handle
	J_STATUS_TYPE retval;
	bool8_t bHasChange;
	uint32_t nCameras;
	uint32_t size;
	int8_t sCameraId[J_CAMERA_ID_SIZE]; // Camera ID

	// Open factory
	retval = J_Factory_Open("" , &hFactory);
	if (retval != J_ST_SUCCESS)
	{
		printf("\tCould not open the factory!\n");
		goto END;
	}

	printf("\tOpened the factory.\n");
	// Update camera list
	retval = J_Factory_UpdateCameraList(hFactory, &bHasChange);
	if (retval != J_ST_SUCCESS)
	{
		printf("\tCould not update the camera list!\n");
		goto END;
	}

	printf("\tUpdated the camera list.\n");
	// Get the number of Cameras
	retval = J_Factory_GetNumOfCameras(hFactory, &nCameras);
	if (retval != J_ST_SUCCESS)
	{
		printf("\tCould not get the number of cameras!\n");
		goto END;
	}

	if (nCameras == 0)
	{
		printf("\tThere is no camera!\n");
		goto END;
	}

	printf("\t%d cameras were found.\n", nCameras);
	// Get camera ID
	size = sizeof(sCameraId);
	retval = J_Factory_GetCameraIDByIndex(hFactory, 0, sCameraId, &size);
	if (retval != J_ST_SUCCESS)
	{
		printf("\tCould not get the camera ID!\n");
		goto END;
	}

	printf("\tcamera 0: %s\n", sCameraId);
	// Open camera
	retval = J_Camera_Open(hFactory, sCameraId, &hCamera);
	if (retval != J_ST_SUCCESS)
	{
		printf("\tCould not open the camera!\n");
		goto END;
	}
	printf("\tOpened camera 0.\n");

	
	END:

	//--------------------------------------------------------------------
	// Start accepting connections
	//--------------------------------------------------------------------

	// Create a continuous loop that checks for connections requests. If a connection
	// request occurs, call the accept function to handle the request.
	printf("Waiting for a client to connect...\n");

	printf("***Hint: Server is ready...run your client program...***\n");

	// Get image...
	THRD_HANDLE hThread;
	//NODE_HANDLE hNode;
	int64_t int64Val;
	SIZE ViewSize = {100, 100};
	POINT TopLeft = {0, 0};

	// Get Width from the camera
	if (J_Camera_GetValueInt64(hCamera, "Width", &int64Val) != J_ST_SUCCESS)
	{
	printf("width\n");
	system ("pause");
	return FALSE;
	}
	ViewSize.cx = (LONG)int64Val; // Set window size cx

	// Get Height from the camera
	if (J_Camera_GetValueInt64(hCamera, "Height", &int64Val) != J_ST_SUCCESS)
	{
	printf("height\n");
	system ("pause");
	return FALSE;
	}
	ViewSize.cy = (LONG)int64Val; // Set window size cy

	// Open stream
	void *vfptr = reinterpret_cast<void*>(StreamCBFunc);
	J_IMG_CALLBACK_FUNCTION *cbfptr = reinterpret_cast<J_IMG_CALLBACK_FUNCTION*>(&vfptr);

	if (J_Image_OpenStream(hCamera,0,NULL,*cbfptr,&hThread,ViewSize.cx*ViewSize.cy*6) != J_ST_SUCCESS)
	{
	printf("open stream\n");
	system ("pause");
	return FALSE;
	}

	// Create a temporary SOCKET object called AcceptSocket for accepting connections.
	SOCKET AcceptSocket;

	char recvbuf[200] = "";
	int bytesRecv = SOCKET_ERROR;


	AcceptSocket = SOCKET_ERROR;

	while (AcceptSocket == SOCKET_ERROR)
			AcceptSocket = accept(m_socket, NULL, NULL);

	while (1)
	{	
		//printf("...tiff\n");
		tictoc(0);
		bytesRecv = recv(AcceptSocket, recvbuf, 32, 0);		

		if(strncmp(recvbuf,"Get1",4)==0)
		{
			imgAq=FALSE;
			imgSeq=TRUE;
			// Acquisition Start
			if (J_Camera_ExecuteCommand(hCamera, "AcquisitionStart") != J_ST_SUCCESS)
			{
				printf("fail:Aquisition start\n");
			system ("pause");
			return FALSE;
			}
			// Message loop
			//while (!_kbhit())
			while (imgAq==FALSE)
			{
				MSG msg;
				if (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
				{
					::TranslateMessage(&msg);
					::DispatchMessage(&msg);
				}
			}
			// Acquisition Stop
			if (J_Camera_ExecuteCommand(hCamera, "AcquisitionStop") != J_ST_SUCCESS)
			{
			printf("fail:Aquisition stop\n");
			system ("pause");
			return FALSE;
			}
			//----------------------------------------------------------------------------
			printf("tictoc:\n");
			tictoc(1);
			Sleep(10);

			send(AcceptSocket, "Done\n", strlen("Done\n"), 0);
			cout  << "imgSeq1:" << imgSeq << '\n';
			
		}else if(strncmp(recvbuf,"Get2",4)==0)
		{
			imgAq=FALSE;
			imgSeq=FALSE;
			// Acquisition Start
			if (J_Camera_ExecuteCommand(hCamera, "AcquisitionStart") != J_ST_SUCCESS)
			{
				printf("fail:Aquisition start\n");
			system ("pause");
			return FALSE;
			}
			// Message loop
			//while (!_kbhit())
			while (imgAq==FALSE)
			{
				MSG msg;
				if (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
				{
					::TranslateMessage(&msg);
					::DispatchMessage(&msg);
				}
			}
			// Acquisition Stop
			if (J_Camera_ExecuteCommand(hCamera, "AcquisitionStop") != J_ST_SUCCESS)
			{
			printf("fail:Aquisition stop\n");
			system ("pause");
			return FALSE;
			}
			//----------------------------------------------------------------------------
			printf("tictoc:\n");
			tictoc(1);
			Sleep(10);

			send(AcceptSocket, "Done\n", strlen("Done\n"), 0);
			cout  << "imgSeq2:" << imgSeq << '\n';

		}else if(strncmp(recvbuf,"End",3)==0)
		{
			printf("\tRecived end command\n");
			send(AcceptSocket, "Terminated\n", strlen("Terminated\n"), 0);
			break;
		}else
			printf("\tRecived undifined command\n");
	}

	//Close stream
	J_Image_CloseStream(hThread);

	// Close camera
	J_Camera_Close(hCamera);
	printf("\tClosed the camera.\n");
	// Close factory
	J_Factory_Close(hFactory);
	printf("\tClosed the factory.\n");

	//END:
	
	return 0;
}