#pragma once
#pragma pack(1)

#define MAX_ID_LEN						16
#define MAX_PASSWORD_LEN				16
#define MAX_MAILADDR_LEN				50
#define MAX_PROGRAM_KEY_LEN				65
#define MAX_PROGRAM_NAME_LEN			50
#define MAX_PROGRAM_COMPANY_LEN			50
#define MAX_PROGRAM_VERSION_LEN			50
#define MAX_PROGRAM_DESCRIPTION_LEN		50
#define MAX_REPLY_CONTENTS_LEN			256
#define MAX_REPORT_CONTENTS_LEN			256
#define RECORD_LEN						14

/** packet type **/
enum 
{
	MESSAGE_TYPE_MEMBER_JOIN = 0,
	MESSAGE_TYPE_MEMBER_LOGIN, 
	MESSAGE_TYPE_MEMBER_LOGOUT,
	MESSAGE_TYPE_MEMBER_JOIN_ACK,
	MESSAGE_TYPE_MEMBER_LOGIN_ACK, 

	MESSAGE_TYPE_VERIFICATION,
	MESSAGE_TYPE_VERIFICATION_ACK, 

	MESSAGE_TYPE_PROGRAM_REGISTER,
	MESSAGE_TYPE_PROGRAM_REGISTER_ACK,

	MESSAGE_TYPE_REPORT_REQUEST, 
	MESSAGE_TYPE_REPORT_REGISTER,
	MESSAGE_TYPE_REPORT_MODIFY,
	MESSAGE_TYPE_REPORT_REMOVE,
	MESSAGE_TYPE_REPORT_LIST,
	MESSAGE_TYPE_REPORT_REGISTER_ACK,
	MESSAGE_TYPE_REPORT_REMOVE_ACK,

	MESSAGE_TYPE_REPLY_REQUEST,
	MESSAGE_TYPE_REPLY_REGISTER,
	MESSAGE_TYPE_REPLY_MODIFY,
	MESSAGE_TYPE_REPLY_REMOVE,
	MESSAGE_TYPE_REPLY_LIST,
	MESSAGE_TYPE_REPLY_REGISTER_ACK,
	MESSAGE_TYPE_REPLY_REMOVE_ACK,
};

class KPacket  
{
public:
	int		m_nPacketSize;
	unsigned int	m_nPacketType;
	KPacket()
	{
		m_nPacketSize = sizeof ( *this );
	}
};


/**** Client -> Server ****/ 
/** Member **/
class KJoinMemberPacket : public KPacket // 회원 가입 패킷 
{
public : 
	char	m_szId[MAX_ID_LEN];
	char	m_szPassword[MAX_PASSWORD_LEN];
	char	m_szMailAddress[MAX_MAILADDR_LEN];
	
	KJoinMemberPacket() 
	{
		memset ( this, 0, sizeof ( *this ) );
		m_nPacketSize = sizeof ( *this );
		m_nPacketType = MESSAGE_TYPE_MEMBER_JOIN;
	}
};

class KLoginPacket : public KPacket // 로그인 패킷 (게스트인 경우 : id = "guest", Password는 확인 안함)
{
public : 
	char	m_szId[MAX_ID_LEN];
	char	m_szPassword[MAX_PASSWORD_LEN];
	
	KLoginPacket() 
	{
		memset ( this, 0, sizeof ( *this ) );
		m_nPacketSize = sizeof ( *this );
		m_nPacketType = MESSAGE_TYPE_MEMBER_LOGIN;
	}
};

class KLogoutPacket : public KPacket // 로그아웃 패킷 (해당 id 로그아웃)
{
public : 
	KLogoutPacket() 
	{
		memset ( this, 0, sizeof ( *this ) );
		m_nPacketSize = sizeof ( *this );
		m_nPacketType = MESSAGE_TYPE_MEMBER_LOGOUT;
	}
};



/** Verification **/
class KVerificationPacket : public KPacket // 검사 패킷 (해당 유저가 해당 키를 검사, 게스트는 id = "guest")
{
public : 
	char	m_szProgramKey[MAX_PROGRAM_KEY_LEN];

	KVerificationPacket()
	{
		memset ( this, 0, sizeof ( *this ) );
		m_nPacketSize = sizeof ( *this );
		m_nPacketType = MESSAGE_TYPE_VERIFICATION;
	}
};



/** Report **/ 
class KRequestReportPacket : public KPacket	// 신고 내용 정보 요청 패킷
{
public : 
	char	m_szProgramKey[MAX_PROGRAM_KEY_LEN];

	KRequestReportPacket()
	{
		memset ( this, 0, sizeof ( *this ) );
		m_nPacketSize = sizeof ( *this );
		m_nPacketType = MESSAGE_TYPE_REPORT_REQUEST;
	}
};

class KReportRegisterPacket : public KPacket // 신고 내용 등록 패킷 (해당 유저가 해당 키를 신고, 게스트는 id = "guest") 
{
public : 
	char	m_szProgramKey[MAX_PROGRAM_KEY_LEN];
	char	m_szContents[MAX_REPORT_CONTENTS_LEN];

	KReportRegisterPacket()
	{
		memset ( this, 0, sizeof ( *this ) );
		m_nPacketSize = sizeof ( *this );
		m_nPacketType = MESSAGE_TYPE_REPORT_REGISTER;
	}
};

class KReportModifyPacket : public KPacket // 신고 내용 수정 패킷
{
public : 
	unsigned int		m_nId;
	char	m_szContents[MAX_REPORT_CONTENTS_LEN];

	KReportModifyPacket()
	{
		memset ( this, 0, sizeof ( *this ) );
		m_nPacketSize = sizeof ( *this );
		m_nPacketType = MESSAGE_TYPE_REPORT_MODIFY;
	}
};

class KReportRemovePacket : public KPacket  // 신고 내용 삭제 패킷 
{
public : 
	unsigned int		m_nId;

	KReportRemovePacket()
	{
		memset ( this, 0, sizeof ( *this ) );
		m_nPacketSize = sizeof ( *this );
		m_nPacketType = MESSAGE_TYPE_REPORT_REMOVE;
	}
};


/** Program Register **/ 
class KProgramRegisterPacket : public KPacket // 프로그램 등록 패킷 
{
public : 
	char	m_szProgramKey[MAX_PROGRAM_KEY_LEN];
	char	m_szProgramName[MAX_PROGRAM_NAME_LEN];
	char	m_szProgramCompany[MAX_PROGRAM_COMPANY_LEN];
	char	m_szProgramVersion[MAX_PROGRAM_VERSION_LEN];
	char	m_szProgramDescription[MAX_PROGRAM_DESCRIPTION_LEN];

	KProgramRegisterPacket()
	{
		memset ( this, 0, sizeof ( *this ) );
		m_nPacketSize = sizeof ( *this );
		m_nPacketType = MESSAGE_TYPE_PROGRAM_REGISTER;
	}
};


/** Reply **/ 
class KRequestReplyPacket : public KPacket // 댓글 내용 정보 요청 패킷
{
public : 
	char	m_szProgramKey[MAX_PROGRAM_KEY_LEN];

	KRequestReplyPacket()
	{
		memset ( this, 0, sizeof ( *this ) );
		m_nPacketSize = sizeof ( *this );
		m_nPacketType = MESSAGE_TYPE_REPLY_REQUEST;
	}
};

class KReplyRegisterPacket : public KPacket // 댓글 등록 패킷
{
public : 
	char	m_szProgramKey[MAX_PROGRAM_KEY_LEN];
	char	m_szContents[MAX_REPLY_CONTENTS_LEN];

	KReplyRegisterPacket()
	{
		memset ( this, 0, sizeof ( *this ) );
		m_nPacketSize = sizeof ( *this );
		m_nPacketType = MESSAGE_TYPE_REPLY_REGISTER;
	}
};

class KReplyModifyPacket : public KPacket // 댓글 수정 패킷
{
public : 
	unsigned int		m_nReplyNum;
	char	m_szContents[MAX_REPLY_CONTENTS_LEN];

	KReplyModifyPacket()
	{
		memset ( this, 0, sizeof ( *this ) );
		m_nPacketSize = sizeof ( *this );
		m_nPacketType = MESSAGE_TYPE_REPLY_MODIFY;
	}
};

class KReplyRemovePacket : public KPacket  // 댓글 삭제 패킷 
{
public : 
	unsigned int		m_nId;

	KReplyRemovePacket()
	{
		memset ( this, 0, sizeof ( *this ) );
		m_nPacketSize = sizeof ( *this );
		m_nPacketType = MESSAGE_TYPE_REPLY_REMOVE;
	}
};





/**** Server -> Client ****/ 
/** Member **/
enum 
{
	MEMBER_JOIN_SUCCESS = 0, 
	MEMBER_JOIN_ERROR_DUPLE, // 해당 아이디 이미 존재 
};
class KJoinMemberAck : public KPacket // 회원가입 응답 
{
public : 
	int m_nResult;

	KJoinMemberAck() 
	{
		memset ( this, 0, sizeof ( *this ) );
		m_nPacketSize = sizeof ( *this );
		m_nPacketType = MESSAGE_TYPE_MEMBER_JOIN_ACK;
	}
};

enum 
{
	MEMBER_LOGIN_SUCCESS = 0,  
	MEMBER_LOGIN_ERROR, // 아이디 혹은 패스워드가 잘못됨
};
class KLoginAck : public KPacket // 로그인 응답 
{
public : 
	int m_nResult;
	
	KLoginAck() 
	{
		memset ( this, 0, sizeof ( *this ) );
		m_nPacketSize = sizeof ( *this );
		m_nPacketType = MESSAGE_TYPE_MEMBER_LOGIN_ACK;
	}
};


/** Verification **/
enum
{
	VERIFICATION_ACK_NOT_INFO = 0, // 정보가 존재하지 않고 키만있는경우 (디비정보에 프로그램명이 NULL인경우)
	VERIFICATION_ACK_EXIST_INFO, // 모든 정보가 존재하는 경우 
};
class KVerificationAck : public KPacket // 클라이언트에서 검사할 경우 응답 (해당키에 해당하는 정보)
{
public : 
	int		m_nResult; 
	char	m_szProgramKey[MAX_PROGRAM_KEY_LEN];
	char	m_szProgramName[MAX_PROGRAM_NAME_LEN];
	char	m_szProgramCompany[MAX_PROGRAM_COMPANY_LEN];
	char	m_szProgramVersion[MAX_PROGRAM_VERSION_LEN];
	char	m_szProgramDescription[MAX_PROGRAM_DESCRIPTION_LEN];
	char	m_szRegisterId[MAX_ID_LEN];
	char	m_szRecordTime[RECORD_LEN];
	unsigned int		m_nMemberAccessCount;
	unsigned int		m_nMemberReportCount;
	unsigned int		m_nGuestAccessCount;
	unsigned int		m_nGuestReportCount;
	unsigned int		m_nReplyCount;
	unsigned int		m_nTotalMemberCount;

	KVerificationAck()
	{
		memset ( this, 0, sizeof ( *this ) );
		m_nPacketSize = sizeof ( *this );
		m_nPacketType = MESSAGE_TYPE_VERIFICATION_ACK;
	}
};


/** Report **/
enum
{
	REPORT_REGISER_SUCCESS = 0, 
	REPORT_REGISER_ERROR_DUPLE, // 이미 신고한 경우(한유저가 한 프로그램을 여러번 신고하는 경우를 막기 위해)
};
class KReportRegisterAck : public KPacket // 신고시 응답
{
public : 
	int m_nResult;

	KReportRegisterAck()
	{
		memset ( this, 0, sizeof ( *this ) );
		m_nPacketSize = sizeof ( *this );
		m_nPacketType = MESSAGE_TYPE_REPORT_REGISTER_ACK;
	}
};

enum
{
	REPORT_REMOVE_SUCCESS = 0, 
	REPORT_REMOVE_ERROR_NOT_EXIST, // 해당 신고 내역이 없는 경우 
};
class KReportRemoveAck : public KPacket // 신고시 응답
{
public : 
	int m_nResult;

	KReportRemoveAck()
	{
		memset ( this, 0, sizeof ( *this ) );
		m_nPacketSize = sizeof ( *this );
		m_nPacketType = MESSAGE_TYPE_REPORT_REMOVE_ACK;
	}
};


class KReportListPacket : public KPacket // 신고 정보를 전송하는 패킷
{
public:
	unsigned int		m_nId; 
	char				m_szRegisterId[MAX_ID_LEN];
	char				m_szProgramKey[MAX_PROGRAM_KEY_LEN];
	char				m_szContents[MAX_REPORT_CONTENTS_LEN];
	char				m_szRecordTime[RECORD_LEN];

	KReportListPacket()
	{
		memset ( this, 0, sizeof ( *this ) );
		m_nPacketSize = sizeof ( *this );
		m_nPacketType = MESSAGE_TYPE_REPORT_LIST;
	}
};


/** Program Register **/ 
enum
{
	PROGRAM_REGISTER_SUCCESS = 0, 
	PROGRAM_REGISTER_ERROR_DUPLE, // 해당 키 값의 정보 이미 존재 
};
class KProgramRegisterAck : public KPacket // 프로그램 등록 응답 
{
public : 
	int m_nResult;

	KProgramRegisterAck()
	{
		memset ( this, 0, sizeof ( *this ) );
		m_nPacketSize = sizeof ( *this );
		m_nPacketType = MESSAGE_TYPE_PROGRAM_REGISTER_ACK;
	}
};


/** Reply **/ 
class KReplyListPacket : public KPacket // 댓글 정보를 전송하는 패킷
{
public:
	unsigned int		m_nId; 
	char				m_szRegisterId[MAX_ID_LEN];
	char				m_szProgramKey[MAX_PROGRAM_KEY_LEN];
	char				m_szContents[MAX_REPLY_CONTENTS_LEN];
	char				m_szRecordTime[RECORD_LEN];

	KReplyListPacket()
	{
		memset ( this, 0, sizeof ( *this ) );
		m_nPacketSize = sizeof ( *this );
		m_nPacketType = MESSAGE_TYPE_REPLY_LIST;
	}
};

enum
{
	REPLY_REGISER_SUCCESS = 0, 
	REPLY_REGISER_ERROR_DUPLE, 
};
class KReplyRegisterAck : public KPacket // 댓글 등록시 응답
{
public : 
	int m_nResult;

	KReplyRegisterAck()
	{
		memset ( this, 0, sizeof ( *this ) );
		m_nPacketSize = sizeof ( *this );
		m_nPacketType = MESSAGE_TYPE_REPLY_REGISTER_ACK;
	}
};

enum
{
	REPLY_REMOVE_SUCCESS = 0, 
	REPLY_REMOVE_ERROR_NOT_EXIST, // 해당 댓글내용이 없는 경우 
};
class KReplyRemoveAck : public KPacket // 댓글 삭제 응답 
{
public : 
	int m_nResult;

	KReplyRemoveAck()
	{
		memset ( this, 0, sizeof ( *this ) );
		m_nPacketSize = sizeof ( *this );
		m_nPacketType = MESSAGE_TYPE_REPLY_REMOVE_ACK;
	}
};

#pragma pack()