#ifndef DEFINE_HEADER
#define DEFINE_HEADER
#include <dirent.h>
#include <errno.h>
#include <libusb.h>
#include <pthread.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
#include <wchar.h>

#include <algorithm>
#include <list>
#include <set>
#include <sstream>
#include <string>
#include <vector>
#include "Property.hpp"
using namespace std;
typedef unsigned char BYTE, *PBYTE;
typedef unsigned char UCHAR;
typedef unsigned short WCHAR;
typedef unsigned short USHORT;
typedef unsigned int UINT;
typedef unsigned int DWORD;
#define ALIGN(x, a) __ALIGN_MASK((x), (a)-1)
#define __ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))
#define RK28_SEC2_RESERVED_LEN 473
#define CHIPINFO_LEN 16
#define RK28_SEC3_RESERVED_LEN 382
#define RKDEVICE_SN_LEN 60
#define RKDEVICE_UID_LEN 30
#define RKDEVICE_MAC_LEN 6
#define RKDEVICE_WIFI_LEN 6
#define RKDEVICE_BT_LEN 6
#define RKDEVICE_IMEI_LEN 15
typedef enum {
	RKNONE_DEVICE = 0,
	RK27_DEVICE = 0x10,
	RKCAYMAN_DEVICE,
	RK28_DEVICE = 0x20,
	RK281X_DEVICE,
	RKPANDA_DEVICE,
	RKNANO_DEVICE = 0x30,
	RKSMART_DEVICE,
	RKCROWN_DEVICE = 0x40,
	RK29_DEVICE = 0x50,
	RK292X_DEVICE,
	RK30_DEVICE = 0x60,
	RK30B_DEVICE,
	RK31_DEVICE = 0x70,
	RK32_DEVICE = 0x80
} ENUM_RKDEVICE_TYPE;
typedef enum { RK_OS = 0, ANDROID_OS = 0x1 } ENUM_OS_TYPE;

typedef enum {
	RKUSB_NONE = 0x0,
	RKUSB_MASKROM = 0x01,
	RKUSB_LOADER = 0x02,
	RKUSB_MSC = 0x04
} ENUM_RKUSB_TYPE;
typedef enum { ENTRY471 = 1, ENTRY472 = 2, ENTRYLOADER = 4 } ENUM_RKBOOTENTRY;

#pragma pack(1)
typedef struct sparse_header_t {
	UINT magic; /* 0xed26ff3a */
	USHORT major_version; /* (0x1) - reject images with higher major versions */
	USHORT minor_version; /* (0x0) - allow images with higer minor versions */
	USHORT file_hdr_sz; /* 28 bytes for first revision of the file format */
	USHORT chunk_hdr_sz; /* 12 bytes for first revision of the file format */
	UINT blk_sz; /* block size in bytes, must be a multiple of 4 (4096) */
	UINT total_blks; /* total blocks in the non-sparse output image */
	UINT total_chunks; /* total chunks in the sparse input image */
	UINT image_checksum; /* CRC32 checksum of the original data, counting "don't
							care" */
	/* as 0. Standard 802.3 polynomial, use a Public Domain */
	/* table implementation */
} sparse_header;
#define SPARSE_HEADER_MAGIC 0xed26ff3a
#define UBI_HEADER_MAGIC 0x23494255
#define CHUNK_TYPE_RAW 0xCAC1
#define CHUNK_TYPE_FILL 0xCAC2
#define CHUNK_TYPE_DONT_CARE 0xCAC3
#define CHUNK_TYPE_CRC32 0xCAC4
typedef struct chunk_header_t {
	USHORT chunk_type; /* 0xCAC1 -> raw; 0xCAC2 -> fill; 0xCAC3 -> don't care */
	USHORT reserved1;
	UINT chunk_sz; /* in blocks in output image */
	UINT total_sz; /* in bytes of chunk input file including chunk header and
					  data */
} chunk_header;

typedef struct {
	USHORT usYear;
	BYTE ucMonth;
	BYTE ucDay;
	BYTE ucHour;
	BYTE ucMinute;
	BYTE ucSecond;
} STRUCT_RKTIME, *PSTRUCT_RKTIME;

typedef struct {
	char szItemName[20];
	char szItemValue[256];
} STRUCT_CONFIG_ITEM, *PSTRUCT_CONFIG_ITEM;
typedef struct {
	char szItemName[64];
	UINT uiItemOffset;
	UINT uiItemSize;
} STRUCT_PARAM_ITEM, *PSTRUCT_PARAM_ITEM;
typedef struct _STRUCT_RKDEVICE_DESC {
	USHORT usVid;
	USHORT usPid;
	USHORT usbcdUsb;
	UINT uiLocationID;
	ENUM_RKUSB_TYPE emUsbType;
	ENUM_RKDEVICE_TYPE emDeviceType;
	void *pUsbHandle;
} STRUCT_RKDEVICE_DESC, *PSTRUCT_RKDEVICE_DESC;
typedef struct {
	DWORD dwTag;
	BYTE reserved[4];
	UINT uiRc4Flag;
	USHORT usBootCode1Offset;
	USHORT usBootCode2Offset;
	BYTE reserved1[490];
	USHORT usBootDataSize;
	USHORT usBootCodeSize;
	USHORT usCrc;
} RK28_IDB_SEC0, *PRK28_IDB_SEC0;

typedef struct {
	USHORT usSysReservedBlock;
	USHORT usDisk0Size;
	USHORT usDisk1Size;
	USHORT usDisk2Size;
	USHORT usDisk3Size;
	UINT uiChipTag;
	UINT uiMachineId;
	USHORT usLoaderYear;
	USHORT usLoaderDate;
	USHORT usLoaderVer;
	USHORT usLastLoaderVer;
	USHORT usReadWriteTimes;
	DWORD dwFwVer;
	USHORT usMachineInfoLen;
	UCHAR ucMachineInfo[30];
	USHORT usManufactoryInfoLen;
	UCHAR ucManufactoryInfo[30];
	USHORT usFlashInfoOffset;
	USHORT usFlashInfoLen;
	UCHAR reserved[384];
	UINT uiFlashSize;
	BYTE reserved1;
	BYTE bAccessTime;
	USHORT usBlockSize;
	BYTE bPageSize;
	BYTE bECCBits;
	BYTE reserved2[8];
	USHORT usIdBlock0;
	USHORT usIdBlock1;
	USHORT usIdBlock2;
	USHORT usIdBlock3;
	USHORT usIdBlock4;
} RK28_IDB_SEC1, *PRK28_IDB_SEC1;

typedef struct {
	USHORT usInfoSize;
	BYTE bChipInfo[CHIPINFO_LEN];
	BYTE reserved[RK28_SEC2_RESERVED_LEN];
	char szVcTag[3];
	USHORT usSec0Crc;
	USHORT usSec1Crc;
	UINT uiBootCodeCrc;
	USHORT usSec3CustomDataOffset;
	USHORT usSec3CustomDataSize;
	char szCrcTag[4];
	USHORT usSec3Crc;
} RK28_IDB_SEC2, *PRK28_IDB_SEC2;

typedef struct {
	USHORT usSNSize;
	BYTE sn[RKDEVICE_SN_LEN];
	BYTE reserved[RK28_SEC3_RESERVED_LEN];
	BYTE wifiSize;
	BYTE wifiAddr[RKDEVICE_WIFI_LEN];
	BYTE imeiSize;
	BYTE imei[RKDEVICE_IMEI_LEN];
	BYTE uidSize;
	BYTE uid[RKDEVICE_UID_LEN];
	BYTE blueToothSize;
	BYTE blueToothAddr[RKDEVICE_BT_LEN];
	BYTE macSize;
	BYTE macAddr[RKDEVICE_MAC_LEN];
} RK28_IDB_SEC3, *PRK28_IDB_SEC3;
#pragma pack()
typedef list<STRUCT_RKDEVICE_DESC> RKDEVICE_DESC_SET;
typedef RKDEVICE_DESC_SET::iterator device_list_iter;
typedef vector<string> STRING_VECTOR;
typedef vector<UINT> UINT_VECTOR;
typedef vector<STRUCT_CONFIG_ITEM> CONFIG_ITEM_VECTOR;
typedef vector<STRUCT_PARAM_ITEM> PARAM_ITEM_VECTOR;
typedef enum {
	TESTDEVICE_PROGRESS,
	DOWNLOADIMAGE_PROGRESS,
	CHECKIMAGE_PROGRESS,
	TAGBADBLOCK_PROGRESS,
	TESTBLOCK_PROGRESS,
	ERASEFLASH_PROGRESS,
	ERASESYSTEM_PROGRESS,
	LOWERFORMAT_PROGRESS,
	ERASEUSERDATA_PROGRESS
} ENUM_PROGRESS_PROMPT;

typedef enum { CALL_FIRST, CALL_MIDDLE, CALL_LAST } ENUM_CALL_STEP;

typedef void (*ProgressPromptCB)(DWORD deviceLayer,
		ENUM_PROGRESS_PROMPT promptID, long long totalValue,
		long long currentValue, ENUM_CALL_STEP emCall);

//	bool WideStringToString(wchar_t *pszSrc, char *&pszDest);
//	bool StringToWideString(char *pszSrc, wchar_t *&pszDest);
#endif
