#ifndef _COMMONSTRUCT_H_
#define _COMMONSTRUCT_H_

#pragma once
#define MAX_STYLE_NUM 64

enum EClientType{
	e_Ac_Windows,
	e_CZ_Android,
	e_CZ_iOS,
	e_Ac_Android,
	e_Ac_iOS,
	e_Web,
	e_Pro_Windows,
	e_SM_Checker,
	e_Pro_Lite
};

enum EStyleState{
	e_OffLine = -2,    		//下线
	e_CheckFail,            //审核未通过
	e_Checking,             //待审核
	e_Distribute,           //发布
	e_UnDownload,           //未下载
	e_Downloading,          //在下载
	e_Downloaded            //已下载
};

enum EPaymentOperation{
	e_PO_Pay4Basic 		= 0x01, //基本功能费
	e_PO_Pay4Compose 	= 0x02, //保存编曲
	e_PO_Pay4Midi 		= 0x04, //导出MIDI
	e_PO_Pay4Audios 	= 0x08, //多音轨输出
	e_PO_Pay4Fonts		= 0x10,	//多音色库
	e_PO_End
};

enum EStyleType{
	e_ST_BEGIN,
	e_ST_Origin,
	e_ST_Temp,
	e_ST_Share,
	e_ST_END
};

enum EMessageType{
	e_InvalidMessage,

	e_versionRequest = 0x01,
	e_versionResponse,

	e_connectRequest = 0x11,
	e_connectResponse,

	e_loginRequest = 0x21,
	e_loginResponse,
	e_verifyRequest,
	e_verifyResponse,
	e_purchaseRequest,
	e_purchaseResponse,
	e_registerRequest,
	e_registerResponse,
	e_checkPaymentRequest,
	e_checkPaymentResponse,
	e_payRequest,
	e_payResponse,
	e_iconRequest,
	e_iconResponse,
	e_logoffRequest,
	e_logoffResponse,

	e_dataSendRequest = 0x41,
	e_dataSendResponse,
	e_dataReceiveRequest,
	e_dataReceiveResponse,

	e_styleUpdateRequest = 0x61,
	e_styleUpdateResponse,
	e_styleInfoRequest,
	e_styleInfoResponse,
	e_styleDataRequest,
	e_styleDataResponse,
	e_styleCheckRequest,
	e_styleCheckResponse,
	e_styleRecomRequest,
	e_styleRecomResponse,

	e_uploadStyleRequest = 0x81,
	e_uploadStyleResponse,
	e_uploadSongRequest,
	e_uploadSongResponse,

	e_qnaUpdateRequest = 0x91,
	e_qnaUpdateResponse,
	e_qnaSubmitRequest,
	e_qnaSubmitResponse,
	e_noticeUpdateRequest,
	e_noticeUpdateResponse,

	e_MessgeTypeEnd
};

enum EExtraInfo{
	e_RequestSuccess,

	e_UpdateNoNeed,		//已是最新版本
	e_UpdateOptional,	//版本可选更新
	e_UpdateMandatory,	//版本强制更新

	e_VerifyInsufficient,

	e_ShareStyle = 0x100,   //分享风格信息
 	e_CheckStyle = 0x101,   //审核风格信息

	e_RequestFailed = 0x8000,
	e_SocketError,
	e_WaitTimeout,
	e_DatabaseError,
	e_ParamError,
	e_LoginPasswordError,
	e_LoginUserNotExist,
	e_InvalidUserID,
	e_InvalidStyleID,

	e_UserCanceled,
	e_NoService,
	e_ServiceBusy,

	e_InvalidDataID,
	e_InvalidPackID,
	e_OutOfBound,
	e_InvalidData,
	e_InvalidAuthority,	//无操作权限
	e_CheckedAlready, //风格已被审核

	e_UsernameExist,
	e_OpenFileFailed,

	e_NeedRepeat,	//需重发消息
	
	e_VipExceeded, //VIP用户设备数超限

   	e_UserLocked, //账户被冻结
	e_UserDeleted, //账户已删除

	e_FormatErr = 0x81000000,		//格式错误
	e_TrkNumErr,					//轨道数不匹配
	e_TrkToMuch,					//轨道数过多
	e_MemErr,						//内存错误
	e_Unsupport,					//不支持的格式
	e_InvalidParam,					//无效参数
	e_FileNotExist,					//指定文件不存在
	e_NoTrack,						//无有效轨道
	e_Unknown,						//未知错误

	e_ExtraEnd
};

#pragma pack (2)

// 通道信息
typedef struct tagChan{
	char no;	//通道号
	char prog;  //乐器号
	char vol;	//音量

	tagChan(){
		no = prog = vol = -1;
	}
}TCHAN, *PTCHAN;

//风格详细信息结构体
typedef struct tagStyleDetail{
	int		size;
	int 	idAuthor;			//作者ID

	short	iTempo;				//原速
	short	iTimesignature;		//节拍 ( 0=4/4, 1=3/4, 2=2/4, 3=6/8 )
	char	type[4];			//风格分类
	char	nSegNum[4];			//伴奏/加花/前奏/尾奏个数

	//以下部分可变长度传输和存储
	char	strAuthor[40];		//作者名称 UTF8
	char 	strStyleName[40];	//风格名称 UTF8
	char 	strDescription[120];	//风格描述 UTF8

	char	aIntroBars[8];		//前奏小节数  (0/2/4/6大调 1/3/5/7小调)
	char	aEndingBars[8];		//尾奏小节数  (0/2/4/6大调 1/3/5/7小调)
	char 	chordRecom[8];		//推荐和声进行

	TCHAN	tracks[4][8][16];  	//伴奏/加花/前奏/尾奏轨道信息 (前/尾奏0/2/4/6大调 1/3/5/7小调)

	tagStyleDetail(){
		size = sizeof(tagStyleDetail);
		idAuthor = iTempo = iTimesignature = 0;
		memset( type, -1, sizeof(type) );
		memset( nSegNum, 0, sizeof(nSegNum) );

		memset( strAuthor, 0, sizeof(strAuthor) );
		memset( strStyleName, 0, sizeof(strStyleName) );
		memset( strDescription, 0, sizeof(strDescription) );

		memset( aIntroBars, 0, sizeof(aIntroBars) );
		memset( aEndingBars, 0, sizeof(aEndingBars) );
		memset( chordRecom, -1, sizeof(chordRecom) );
	}
}TSTYLEDETAIL, *PTSTYLEDETAIL;

typedef struct tagTrackOld
{
	int iStyleId;	//0 = 原创文件输入？
	BYTE iStyleLoc; //风格位置 0=官方，1=本地，2=临时
	BYTE iSegNo;	//片段号 VAR:0-3, FILL:0-1, INTRO/ENDING: 0-3 [+(1...2 * 16)指定大小调]
	BYTE iChanNo;	//通道号 0-15 9为打击乐轨道
	BYTE iChanSpec;	//指定通道号，组合风格时防止chan冲突
	BYTE iProg;	//乐器号 0-127
	BYTE nVol;	//音量	0-127

	tagTrackOld(){
		memset( this, 0, sizeof(tagTrackOld) );
	};
}TTrackOld;

typedef struct tagTrackOldProj
{
	UINT iStyleLoc;	//风格位置ID
	UINT iStyleId;	//0 = 原创文件输入
	BYTE iSegNo;	//片段号 VAR:0-7, FILL:0-7, INTRO/ENDING: 0-3 [+(1...2 * 16)指定大小调]
	BYTE iChanNo;	//通道号 0-15 9为打击乐轨道
	BYTE iChanSpec;	//指定通道号，组合风格时防止chan冲突
	BYTE iProg;		//乐器号 0-127
	BYTE nVol;		//音量	0-127
	BYTE rsvd;
}TTrackOldProj;

typedef struct tagComposeTrack
{
	UINT iStyleLoc;	//风格位置ID
	UINT iStyleId;	//0 = 原创文件输入
	BYTE iSegNo;	//片段号 VAR:0-7, FILL:0-7, INTRO/ENDING: 0-3 [+(1...2 * 16)指定大小调]
	BYTE iChanNo;	//通道号 0-15 9为打击乐轨道
	BYTE iChanSpec;	//指定通道号，组合风格时防止chan冲突
	BYTE iProg;		//乐器号 0-127
	BYTE nVol;		//音量	0-127
	BYTE iFile;	    //文件号，防止chan冲突
	char iPan;		//声像 -63=left, 0=middle, 63=right
	char nGain;		//增益 -127<0<+127

	tagComposeTrack(){
		memset( this, 0, sizeof(tagComposeTrack) );
	};

	tagComposeTrack( tagComposeTrack* src ){
		memcpy( this, src, sizeof(tagComposeTrack) );
	};
}TComposeTrack;

typedef struct tagTrack
{
	UINT iStyleLoc; //位置id  0=官方 1=分享 -1=临时 其它=本地
	UINT iStyleId;	//0 = 原创文件输入？
	BYTE iSegNo;	//片段号 VAR:0-3, FILL:0-1, INTRO/ENDING: 0-3 [+(1...2 * 16)指定大小调]
	BYTE iChanNo;	//通道号 0-15 9为打击乐轨道
	BYTE iChanSpec;	//指定通道号，组合风格时防止chan冲突
	BYTE iProg;		//乐器号 0-127
	BYTE iProgOrig; //原始乐器号
	char nVol;		//音量	0-127    nVol>=0x80 静音
	char nVolOrig; 	//原始音量
	BYTE iBank;		//音源号 -1=全局SF2, other为指定音源
	BYTE iFile;		//文件号 处理chan冲突
	char rsvd;		//对齐字节

	tagTrack(){
		memset( this, 0, sizeof(tagTrack) );
		iFile = iBank = 0xFF;
	};

	tagTrack( tagTrack* src ){
		memcpy( this, src, sizeof(tagTrack) );
	};
}TTrack;

typedef struct tagBarChords
{
	//每小节最多4个和弦
	BYTE iKey[4];	//和弦调号
	BYTE iType[4];	//和弦种类

	tagBarChords(){
		memset( this, -1, sizeof(tagBarChords) );
	};

	tagBarChords( tagBarChords* src ){
		memcpy( this, src, sizeof(tagBarChords) );
	};
} TBarChords; //和弦小节（非前间尾奏段）

typedef struct tagStage
{
	char iSegType;	//片段类型 0=VAR, 1=FILL, 2=INTRO, 3=ENDING
	char iSegKey;	//片段调号
	WORD reserved; 	//保留字段，对齐字节

	int nBarNum;	//段落长度
	TBarChords* aChords; //各小节和弦

	int nTrkNum;	//轨道数
	TComposeTrack* aTracks; //轨道数组

	tagStage(){
		memset( this, 0, sizeof(tagStage) );
	};

	tagStage( tagStage* src ){
		memcpy( this, src, sizeof(tagStage) );
		if( src->aTracks ){
			aTracks = new TComposeTrack[nTrkNum];
			memcpy( aTracks, src->aTracks, sizeof(TComposeTrack)*nTrkNum );
		}

		if( src->aChords ){
			aChords = new TBarChords[nBarNum];
			memcpy( aChords, src->aChords, sizeof(TBarChords)*nBarNum );
		}
	};

	~tagStage(){
		if( aTracks )
			delete[] aTracks;
		if( aChords )
			delete[] aChords;
	}
} TStage; //编曲时用的结构


//版本结构体
typedef struct
{
	WORD majorVersion;	//主版本号
	WORD minorVersion;	//次版本号（客户端类型0=Windows版, 1=Android版, 2=iOS版, 3=风格合成, 4=风格审核 )
	WORD modifyVersion;  //修改版本号
	WORD buildVersion;	//编译版本号
}TVERSION, *PTVERSION;

#define MAX_DESCRIB_LENGTH		1024

//软件信息结构体
typedef struct tSoftwareInfo{
	int		size;
	TVERSION version;
    UINT  	nFileSize;
	UINT  	tIssueDate;	
	char 	strDescribe[MAX_DESCRIB_LENGTH];
	
	tSoftwareInfo(){ 
		memset( this, 0, sizeof(tSoftwareInfo) ); 
		size = sizeof(tSoftwareInfo); 
	};
} TSOFTWAREINFO, *PTSOFTWAREINFO;

#pragma pack (4)

//账户信息结构体
typedef struct tAccountInfo{
	int 	ID;		 //用户ID
	UINT	authority;	//用户权限
	int		balance;	//帐户余额(唱作音符)
	int		pops;		//魅力值
	int     fans;		//粉丝数
	int     songs;		//歌曲数
	int		vipPeriod;	//VIP时长：-1=终身 0=非VIP 其它=vip剩余秒数

	tAccountInfo(){
		memset( this, 0, sizeof(tAccountInfo) );
	};
}TACCOUNTINFO, *PTACCOUNTINFO;

//用户信息结构体
typedef struct tUserInfo{
	char    strUserName[32];
	char    strPassword[80];
	char	strNickName[32]; //用户昵称
	char 	strIconFile[32]; //用户头像
	TACCOUNTINFO accountInfo;  //账户信息
	int		ownStyleNum; //已购买风格数
	int		arrStyleId[16]; //已购买风格ID数组

	tUserInfo(){
		memset( strUserName, 0, 32 );
		memset( strPassword, 0, 80 );
		memset( strNickName, 0, 32 );
		memset( strIconFile, 0, 32 );
		memset( arrStyleId, 0, 16 );
		ownStyleNum = 0;
	};
}TUSERINFO,*PTUSERINFO;

//字符串对结构体
typedef struct tStringPair{
	char str1[320];
	char str2[640];

	tStringPair(){
		memset( str1, 0, 320 );
		memset( str2, 0, 640 );
	}
} TSTRINGPAIR, *PTSTRINGPAIR;

//上传歌曲信息结构体
typedef struct tSongInfo{
	int		size;				//结构大小
	char	strSongName[64];	//歌曲名
	int		iTempo;				//速度
	char	iTS;				//节拍
	char	iCreation;			//创作类型 (1:原创 3:改编)
	char	iSubmit;			//提交审核状态(0:不提交，1:自动提交)
	char	iSingerType;		//演唱人类别 (1：男；2：女；3：组合；4：其他；0：未知)
	char	strSinger[32];		//演唱
	char	strOriginal[32];	//原唱
	char	strLyricist[32];	//作词
	char	strComposer[32];	//作曲
	char	strArranger[32];	//编曲
	char	iMusicStyle[4];		//曲风
	UINT	aStyleIDs[32];		//使用的风格ID
	char	strDescription[640];//歌曲描述
	char*	strLyric;			//歌词
	char*	strMp3Name;			//mp3临时文件
	char*	strIconName;		//封面临时文件

	//上传工程文件
	UINT    cpjVersion;         //工程版本号
	int     cpjPrice;           //下载收费
	char*   strCpjName;         //工程文件名


	tSongInfo(){
		memset( this, 0, sizeof(tSongInfo) );
		memset( iMusicStyle, -1, 4 );
		size = sizeof(tSongInfo);
	};

	~tSongInfo(){
		if( strLyric )
			delete[] strLyric;
		if( strMp3Name )
			delete[] strMp3Name;
		if( strIconName )
			delete[] strIconName;
		if( strCpjName )
			delete[] strCpjName;
	};
} TSONGINFO, *PTSONGINFO;

//上传歌曲返回分享信息结构
typedef struct tShareInfo{
	UINT	idSong;				//歌曲ID
	char	strSongURL[256];	//歌曲文件URL
	char	strCoverURL[256];	//歌曲封面URL

	tShareInfo(){
		memset( this, 0, sizeof(tShareInfo) );
	};
} TSHAREINFO, *PTSHAREINFO;

#pragma pack()

#endif //_COMMONSTRUCT_H_