#pragma once
//#include "KsCPP_Exports.h"
#include <afxwin.h>
#include <cstdint>
#include <string>
#include "StringHelper.h"

template <typename T = CComboBox>
class  _CKsComboBox :  public T
{
public:	
	using CComboBox::AddString;

	int AddString(const std::wstring& str)
	{
		return CComboBox::AddString(str.c_str());
	}

	int AddString(const std::string& str)
	{
		return CComboBox::AddString(utf8_16(str).c_str());
	}

	void AddStrings(const wchar_t *const* str, size_t num) {
		for (int i = 0; i < num; i++) {
			AddString(str[i]);
		}
	}

	void AddStrings(const char *const* str, size_t num) {
		for (int i = 0; i < num; i++) {
			AddString(utf8_16(str[i]).c_str());
		}
	}

	template <typename T, typename = typename std::enable_if<std::is_integral<T>::value>::type>
	void AddStrings(const wchar_t* const * str, const T *val, size_t num) {
		for (int i = 0; i < num; i++) {
			AddString(str[i]);
			SetItemData(i, val[i]);
		}
	}

	template <typename T, typename = typename std::enable_if<std::is_integral<T>::value>::type>
	void AddStrings(const char* const* str, const T* val, size_t num) {
		for (int i = 0; i < num; i++) {
			AddString(utf8_16(str[i]).c_str());
			SetItemData(i, val[i]);
		}
	}

	template <typename T, typename = typename std::enable_if<std::is_integral<T>::value>::type>
	void AddStrings(const T *val, size_t num, int w = 0)
	{
		CString tmp;

		if (w == 0) {
			for (int i = 0; i < num; i++) {
				tmp.Format(_T("%d"), val[i]);
				AddString(tmp);
			}
		}
		else {
			CString formatStr;
			formatStr.Format(_T("%%dd"), w);
			for (int i = 0; i < num; i++) {
				tmp.Format(formatStr, val[i]);
				AddString(tmp);
			}
		}
	}

	template<typename STRT, typename T> //T为整形或枚举
	int AddWithValue(STRT str, T val)
	{
		auto index = AddString(str);
		if (index >= 0) {
			SetItemData(index, (DWORD_PTR)val);
		}
		return index;
	}

	template<typename STRT, typename T>
	int AddWithPtr(STRT str, T* val)
	{
		auto index = AddString(str);
		if (index >= 0) {
			SetItemDataPtr(index, val);
		}
		return index;
	}

	uint16_t ToUShort(uint16_t def=0, bool *ok=nullptr) {
		CString tmp;
		int index = GetCurSel();
		if (index < 0) {
			if (ok) *ok = false;
			return def;
		}
		else {
			GetLBText(index, tmp);
			if (ok) *ok = true; //注意没有判断是否是数值串
			return uint16_t(_tcstol(tmp, NULL, 10));
		}
		
	};

	uint8_t ToU8(uint8_t def = 0, bool* ok = nullptr) {
		CString tmp;
		int index = GetCurSel();
		if (index < 0) {
			if (ok) *ok = false;
			return def;
		}
		else {
			GetLBText(index, tmp);
			if (ok) *ok = true; //注意没有判断是否是数值串
			return uint8_t(_tcstol(tmp, NULL, 10));
		}

	};

	// 获取当前选项的字符串
	bool getCurrentText(CString& strSelectedText) {
		int nSel = GetCurSel(); // 假设m_ComboBox是你的CComboBox对象  

		if (nSel != CB_ERR) // 检查是否有选中项  
		{
			GetLBText(nSel, strSelectedText); // 获取选中的文本  
			return true;
		}
		return false;
	}

	// Combo选择指定字符串的选项
	void setCurrentText (const CString& str, bool must_exist=false) {
		int index = FindStringExact(0, str);
		if (index >= 0) { // 注意选项必须存在！
			SetCurSel(index);
		}
		else {
			SetCurSel(-1);
		}
		if (!must_exist) {
			SetWindowText(str);
		}
		
	};

	template <typename T, typename = typename std::enable_if<std::is_integral<T>::value>::type>
	void setCurrentNumberText(const T &val, bool must_exist = false) {
		CString str;
		str.Format(_T("%d"), val);
		int index = FindStringExact(0, str);
		if (index >= 0) { // 注意选项必须存在！
			SetCurSel(index);
		}
		else {
			SetCurSel(-1);
		}
		if (!must_exist) {
			SetWindowText(str);
		}
	};

	template <typename T, typename = typename std::enable_if<std::is_integral<T>::value>::type>
	int FindItemData(T val) {
		for (int index = 0; index < GetCount(); index++) {
			auto v = T(CComboBox::GetItemData(index));
			if (val == v) {
				return index;
			}
		}
		return -1;
	}

	int FindItemDataPtr(void* ptr) {
		for (int index = 0; index < GetCount(); index++) {
			if (ptr == CComboBox::GetItemDataPtr(index)) {
				return index;
			}
		}
		return -1;
	}

	template <typename T, typename = typename std::enable_if<std::is_integral<T>::value>::type>
	int SetCurSelByData(T val, bool clearifnotfound=true) {
		auto index = FindItemData(val);
		if (index >= 0) {
			SetCurSel(index);
			return index;
		} else {
			if (clearifnotfound) SetCurSel(-1);
			return CB_ERR;
		}
	}

	int SetCurSelByData(void* ptr, bool clearifnotfound=true) {
		auto index = FindItemDataPtr(ptr);
		if (index >= 0) {
			SetCurSel(index);
			return index;
		} else {
			if (clearifnotfound) SetCurSel(-1);
			return CB_ERR;
		}
	}

	uint32_t GetCurData()
	{
		auto index = GetCurSel();
		ASSERT(index >= 0);
		return uint32_t(GetItemData(index));
	}

	void * GetCurDataPtr()
	{
		auto index = GetCurSel();
		ASSERT(index >= 0);
		return GetItemDataPtr(index);
	}
};

// 不同基类特例化
template class _CKsComboBox<CComboBox>;
template class _CKsComboBox<CBCGPComboBox>;

typedef _CKsComboBox<CComboBox>		CKsComboBox;
typedef _CKsComboBox<CBCGPComboBox> CKsBCGPComboBox;
