#ifndef __Dictionary_H__
#define __Dictionary_H__
#include"pmc_types.h"
#include"CRemoteLog.h"
template <class T,int MAX_SIZE>
class Dictionary {
private:
	char keys[MAX_SIZE][MAX_NAME_LEN];
	T    values[MAX_SIZE];
	
	int findInsertPosition(const char* newKey) {
		if (length == 0) {
			return 0;
		}
		int pos1 = 0;
		int pos2 = length - 1;
		while (pos1<=pos2) {
			int pos = (pos1 + pos2) / 2;
			int compare = strcmp(newKey, keys[pos]);
			if (compare > 0) {
				pos1 = pos + 1;
			}
			else if (compare < 0) {
				pos2 = pos - 1;
			}
			else {
				return pos;
			}
		}
		return pos1;

	}
public:
	int length;
	int size() {
		return length;
	}
	Dictionary() { 
		memset(keys, '\0', sizeof(keys));
		memset(values, '\0', sizeof(values));
		length = 0;
	}
	void clear() {
		memset(keys, '\0', sizeof(keys));
		memset(values, '\0', sizeof(values));
		length = 0;
	}
	//实际存储的是T，但get返回的是T指针，比引用简单些
	T* get(const char* key) {
		if (length == 0) {
			return NULL;
		}
		int pos = findInsertPosition(key);
		if (pos < 0 || pos >= length) {
			return NULL;
		}
		if (strcmp(key, keys[pos]) != 0) {
			return NULL;
		}
		return &values[pos];
	}
#ifdef _DEBUG
	T* getOrCreate(const char* key, const char* file = __FILE__, int line = __LINE__) {
		if (length == 0) {
			strcpy_debug(keys[0], key, sizeof(keys[0]), file, line);
			memset(&values[0], '\0', sizeof(T));
			length++;
			return &values[0];

		}
		int pos = findInsertPosition(key);
		if (pos >= 0 && pos < length && strcmp(key, keys[pos]) == 0) {
			return &values[pos];
		}
		if (length >= MAX_SIZE) {
			logger->info("Dictionary too long[%d][%d]", length, MAX_SIZE);
			return NULL;
		}
		for (int index = length; index > pos; index--) {
			memcpy(&values[index], &values[index - 1], sizeof(T));
			strcpy_debug(keys[index], keys[index - 1], sizeof(keys[index]), file, line);
		}
		strcpy_debug(keys[pos], key, sizeof(keys[pos]), file, line);
		memset(&values[pos], '\0', sizeof(T));
		length++;
		return &values[pos];
	}
#else
	T* getOrCreate(const char* key) {
		if (length == 0) {
			strcpy(keys[0], key);
			memset(&values[0], '\0', sizeof(T));
			length++;
			return &values[0];

		}
		int pos = findInsertPosition(key);
		if (pos >= 0 && pos < length && strcmp(key, keys[pos]) == 0) {
			return &values[pos];
		}
		if (length >= MAX_SIZE) {
			logger->info("Dictionary too long[%d][%d]", length, MAX_SIZE);
			return NULL;
		}
		for (int index = length; index > pos; index--) {
			memcpy(&values[index], &values[index - 1], sizeof(T));
			strcpy(keys[index], keys[index - 1]);
		}
		strcpy(keys[pos], key);
		memset(&values[pos], '\0', sizeof(T));
		length++;
		return &values[pos];
	}
#endif
#ifdef _DEBUG
	void set(const char* key, const T& value,const char*file=__FILE__,int line=__LINE__) {
		if (length == 0) {
			strcpy_debug(keys[0], key,sizeof(keys[0]),file,line);
			memcpy(&values[0], &value, sizeof(T));
			length++;
			return;
		}
		int pos = findInsertPosition(key);
		if (pos >= 0 && pos < length && strcmp(key, keys[pos]) == 0) {
			memcpy(&values[pos], &value, sizeof(T));
			return;
		}
		if (length >= MAX_SIZE) {
			logger->info("Dictionary too long[%d][%d]", length, MAX_SIZE);
			return;
		}
		for (int index = length; index > pos; index--) {
			memcpy(&values[index], &values[index - 1], sizeof(T));
			strcpy_debug(keys[index], keys[index - 1],sizeof(keys[index]),file,line);
		}
		strcpy_debug(keys[pos], key,sizeof(keys[pos]),file,line);
		memcpy(&values[pos], &value, sizeof(T));
		length++;

	}
#else
	void set(const char* key, const T& value, const char* file = __FILE__, int line = __LINE__) {
		if (length == 0) {
			strcpy(keys[0], key);
			memcpy(&values[0], &value, sizeof(T));
			length++;
			return;
		}
		int pos = findInsertPosition(key);
		if (pos >= 0 && pos < length && strcmp(key, keys[pos]) == 0) {
			memcpy(&values[pos], &value, sizeof(T));
			return;
		}
		if (length >= MAX_SIZE) {
			logger->info("Dictionary too long[%d][%d]", length, MAX_SIZE);
			return;
		}
		for (int index = length; index > pos; index--) {
			memcpy(&values[index], &values[index - 1], sizeof(T));
			strcpy(keys[index], keys[index - 1]);
		}
		strcpy(keys[pos], key);
		memcpy(&values[pos], &value, sizeof(T));
		length++;

	}
#endif
	
	T* getByIndex(int index) {
		if (index < 0) {
			return NULL;
		}
		if (index >= length) {
			return NULL;
		}
		return &values[index];
	}
};

#endif