#ifndef __WV_COMMON
#define __WV_COMMON

#ifndef UNICODE
	#define UNICODE
#endif	//UNICODE

#include <WinSock2.h>
#include <WS2tcpip.h>
#include <MSWSock.h>
#include <Windows.h>
#include <CommCtrl.h>
#include <strsafe.h>
#include "resource.h"
#include "VideoInputC.h"

#ifdef _DEBUG
#include "MemDbg.h"
#endif

// Common
#define VWM_SETFRAME	(WM_USER+1)
#define WVM_DESTROYME	(WM_USER+2)

#define DefAlloc(size)	HeapAlloc(g_hProcHeap, 0, (size))
#define DefFree(lpVoid)	HeapFree(g_hProcHeap, 0, (LPVOID)(lpVoid))

typedef struct ENDPOINTtag
{
	DWORD		dwAddr;
	USHORT		uPort;
} ENDPOINT, *LPENDPOINT;

// CTWMD
#define WV_CTWMDM	(WM_APP+1)
typedef struct CTWMDtag
{
	HWND				hWnd;
	UINT				uMsg;
	WPARAM				wParam;
	LPARAM				lParam;
	LRESULT				lResult;
	CRITICAL_SECTION	cs;
	DWORD				dwOwnerId;
	HHOOK				hhMsgFilter;
	HANDLE				hMsgProcessed;
} CTWMD, *LPCTWMD;


// List
typedef BOOL (__fastcall *LPEQUALFCN)(LPVOID, LPVOID);

typedef struct LISTITEMtag
{
	LPVOID				lpData;
	struct LISTITEMtag	*lpNext;
} LISTITEM, *LPLISTITEM;

typedef struct LISTtag
{
	LPVOID				Reserved;
	LPLISTITEM			lpFirst;
	LPLISTITEM			lpLast;
	INT					iCount;
	LPEQUALFCN			lpEqFcn;	
	CRITICAL_SECTION	cs;
} LIST, *LPLIST;

typedef struct LISTENUMtag
{
	LPLIST		lpLs;
	LPLISTITEM	lpCurrentItem;
} LISTENUM, *LPLISTENUM;


// Frame Findow
typedef struct WNDSTRUCTtag
{
	HWND	hWnd;
	HMENU	hMenu;	
} WNDSTRUCT, *LPWNDSTRUCT;

typedef struct SETTINGStag
{
	INT			iPort;	
	INT			iVIDeviceID;
	INT			iVideoW;
	INT			iVideoH;
	HKEY		hRegKey;
} SETTINGS, *LPSETTINGS;

// RWLock
typedef struct RWLOCKtag
{
	HANDLE				hDoRead;
	HANDLE				hDoWrite;
	LONG				cReaders;
	CRITICAL_SECTION	cs;
} RWLOCK, *LPRWLOCK;

// WVFrame
#define	WVF_COMPRESSION_NONE	0
#define WVF_COMPRESSION_MJPEG	1

typedef struct WVFRAMEtag
{
	INT			iWidth;
	INT			iHeight;
	ULONG		uFrameSize;
	INT			iCompression;
	ULONG		uBufSize;
	LPBYTE		lpFrame;
} WVFRAME, *LPWVFRAME;

// FrameGrabber
typedef struct FGSTRUCTtag
{
	WVFRAME				wvfFrame;
	INT					iDeviceID;	
	UINT				nFrameCnt;	
	RWLOCK				rwl;
	HANDLE				hThread;
	DWORD				dwThreadID;
	HANDLE				hJobsDone;
	CRITICAL_SECTION	csMsgLoop;
	BOOL				bThrdIsRunning;
	LRESULT				lResult;	
	BOOL				bIsSetup;
} FGSTRUCT, *LPFGSTRUCT;

typedef struct FGSETUPtag
{
	INT		iWidth;
	INT		iHeight;
	INT		iDeviceID;	
} FGSETUP, *LPFGSETUP;


// Buffer
typedef struct BUFFERtag
{
	OVERLAPPED	ol;
	ULONG		cSize;
	LPVOID		lpBuffer;
	ULONG		cOffset;
	WSABUF		wsa;	
	ULONG		cPacketSize;
	DWORD		dwFlags;
	BOOL		isSending;
} BUFFER, *LPBUFFER;

// Networking

typedef struct IOCPINFOtag
{	
	HANDLE			hIocp;
	INT				cNumberOfThreads;
	LPHANDLE		aThreads;
	LPLIST			liConnections;
	LPVOID			lpData;
} IOCPINFO, *LPIOCPINFO;



#define MSG_CREATE		0
#define	MSG_COMPLETION	1
#define MSG_DESTROY		2
#define MSG_ERROR		3

#define	CS_CONNECTED	1
#define CS_GOINGDOWN	2
#define	CS_DOWN			3


typedef struct CONNECTIONtag
{
	SOCKET				sdSocket;
	DWORD				dwRemoteAddr;
	USHORT				uRemotePort;
	ULONG_PTR			(__stdcall *lpProc)(LPCONNECTION, UINT, UINT_PTR, ULONG_PTR);
	LPIOCPINFO			lpIociParent;	
	LPVOID				lpProtocolData;
	CRITICAL_SECTION	cs;
	UINT				uState;
	HANDLE				hEvent;
	HANDLE				hAllOperationsDone;
	UINT				cOverlappedOperations;
	LPBUFFER			lpDisconnectBuffer;
} CONNECTION, *LPCONNECTION;

typedef ULONG_PTR	(__stdcall *LPPROTOCOLPROC)(LPCONNECTION lpCon, UINT uMsg, UINT_PTR uParamA, ULONG_PTR uParamB);

// Server
typedef struct SERVERtag
{
	SOCKET		sdListener;
	LPLIST		liClients;
	HANDLE		hAcceptorThread;
	LPIOCPINFO	lpIoci;	
	LPFGSTRUCT	lpFgs;	
	HANDLE		hEvents[2];
} SERVER, *LPSERVER;

// Protokol
#define CCS_RECV_HEADER		1
#define CCS_RECV_DATA		2
typedef struct	CLIENTDATAtag
{
	HWND		hWndVideo;
	HWND		hWndClient;
	UINT		uState;
	WVFRAME		wvfMain;
	BUFFER		bufRecv;
	BYTE		bPackedHeader[4*sizeof(INT)];
} CLIENTDATA, *LPCLIENTDATA;

#define SCS_SEND_HEADER		1
#define SCS_SEND_DATA		2
typedef struct SERVERDATAtag
{	
	WVFRAME		wvfMain;
	BUFFER		bufMain;	
	BUFFER		bufRecv;
	UINT		uState;
	BYTE		bPackedHeader[4*sizeof(INT)];
	LPSERVER	lpServer;
} SERVERDATA, *LPSERVERDATA;	

extern SETTINGS		g_sSettings;
extern HINSTANCE	g_hInstance;
extern WNDSTRUCT	g_wndFrame;
extern TCHAR		g_szVideoWndClassName[];
extern HANDLE		g_hProcHeap;
extern DWORD		g_dwMainThrdId;
extern LPCTWMD		g_lpCtwmd;
extern LPFGSTRUCT	g_lpFrameGrabber;


#endif	//__WV_COMMON