#pragma once

#include "GdCPP_Exports.h"
#include "spdlog/fmt/fmt.h"
#include "spdlog/fmt/xchar.h"
#include "StringHelper.h"
#include <WS2tcpip.h>
#include <vector>
#include <ifdef.h> //for IF_OPER_STATUS

/// @brief ipv4地址类，在sockaddr_in基础上增加字符与ip互转的函数
struct GDCPP_API ipv4addr
	: public sockaddr_in
{
	ipv4addr()
	{
		zero();
	}
	// 复制构造函数
	ipv4addr(const ipv4addr &src)
	{
		memcpy(this, &src, sizeof(sockaddr_in));
	}

	ipv4addr(const sockaddr_in* src)
	{
		if (src) {
			if (src->sin_family == AF_INET) { //确认src是ipv4地址
				memcpy(this, src, sizeof(sockaddr_in));
				return;
			}
		}
		zero();
	}

	ipv4addr(const sockaddr* src)
	{
		if (src) {
			if (src->sa_family == AF_INET) { //确认src是ipv4地址
				memcpy(this, src, sizeof(sockaddr_in));
				return;
			}
		}
		zero();
	}

	ipv4addr(uint32_t ip, uint16_t port=0)
	{
		sin_family = AF_INET;
		sin_addr.S_un.S_addr = ip;
		sin_port = htons(port);
	}
	ipv4addr(const char* ip, uint16_t port = 0)
	{
		sin_family = AF_INET;
		inet_pton(AF_INET, ip, &sin_addr); 
		sin_port = htons(port);
	}

	ipv4addr(const std::string& ip, uint16_t port = 0)
	{
		sin_family = AF_INET;
		inet_pton(AF_INET, ip.c_str(), &sin_addr);
		sin_port = htons(port);
	}

	/// @brief 设置ipv4地址
	/// @param ip 192.168.0.1 32位数值是0x0100A8C0，字节循序是C0 A8 00 01
	/// @param port 
	void set(uint32_t ip, uint16_t port = 0)
	{
		sin_family = AF_INET;
		sin_addr.S_un.S_addr = ip;
		sin_port = htons(port);
	}
	void set(const char* ip, uint16_t port = 0)
	{
		sin_family = AF_INET;
		inet_pton(AF_INET, ip, &sin_addr);
		sin_port = htons(port);
	}

	void set(const std::string& ip, uint16_t port = 0)
	{
		sin_family = AF_INET;
		inet_pton(AF_INET, ip.c_str(), &sin_addr);
		sin_port = htons(port);
	}

	// 仅设置端口
	void setPort(uint16_t port)
	{
		sin_port = htons(port);
	}
	//改成广播地址
	void toBoradcast() {
		sin_addr.S_un.S_addr &= 0x00FFFFFF;
		sin_addr.S_un.S_addr |= 0xFF000000;
	}

	void toBoradcast(ipv4addr &dst) {
		dst = *this;
		dst.toBoradcast();
	}

	void zero()
	{
		sin_family = AF_INET;
		sin_port = 0;
		sin_addr.s_addr = 0;
		for (auto& i : sin_zero) i = 0;
	}

	uint32_t ip() const { return sin_addr.s_addr; }
	uint32_t port() const { return htons(sin_port);	}

	std::string ipStr() const
	{
		const auto& b = sin_addr.S_un.S_un_b;
		return fmt::format("{:d}.{:d}.{:d}.{:d}", b.s_b1, b.s_b2, b.s_b3, b.s_b4);
	}

	std::wstring ipWStr() const
	{
		const auto& b = sin_addr.S_un.S_un_b;
		return fmt::format(L"{:d}.{:d}.{:d}.{:d}", b.s_b1, b.s_b2, b.s_b3, b.s_b4);
	}

	std::string addrStr() const
	{
		const auto& b = sin_addr.S_un.S_un_b;
		return fmt::format("{:d}.{:d}.{:d}.{:d}:{}", b.s_b1, b.s_b2, b.s_b3, b.s_b4, htons(sin_port));
	}

	std::wstring addrWStr() const
	{
		const auto& b = sin_addr.S_un.S_un_b;
		return fmt::format(L"{:d}.{:d}.{:d}.{:d}:{}", b.s_b1, b.s_b2, b.s_b3, b.s_b4, htons(sin_port));
	}

	operator const sockaddr* () const {
		return (const sockaddr*)this;
	}

	operator sockaddr* () {
		return (sockaddr*)this;
	}

	bool operator  == (const ipv4addr & src) const {
		return (src.sin_family== AF_INET && sin_port == src.sin_port && sin_addr.s_addr == src.sin_addr.s_addr);
	}
	bool operator != (const ipv4addr& src) const {
		return !(*this == src);
	}
	bool operator < (const ipv4addr& src) const {
		return (sin_addr.s_addr < src.sin_addr.s_addr) || (sin_addr.s_addr == src.sin_addr.s_addr && sin_port < src.sin_port);
	}
};


struct GDCPP_API sAdapter
{
	IF_OPER_STATUS OperStatus;	// 常见IfOperStatusUp，IfOperStatusDown
	std::wstring Description;	// 例：Realtek PCIe GbE Family Controller
	std::wstring FriendlyName;	// 例：WLAN，以太网
	ipv4addr IpAddr;

	sAdapter(const wchar_t* desc = nullptr, const wchar_t* name = nullptr)
		: Description(desc == nullptr ? L"" : desc)
		, FriendlyName(name == nullptr ? L"" : name)
	{

	}

	sAdapter(const sAdapter& s)
		: OperStatus(s.OperStatus)
		, Description(s.Description)
		, FriendlyName(s.FriendlyName)
		, IpAddr(s.IpAddr)
	{

	}
};


class GDCPP_API CAdapterList 
{
public:
	CAdapterList() = default;

	// 排除ExcludedNetAdpter列举的网卡（蓝牙、vmware等）
	static std::vector<std::wstring> gExcludedList;

	enum {
		// 排除Software Loopback Interface 1
		Exclude_Loopback = 0x00000001,
		// 排除vmware网卡
		Exclude_Vmware = 0x00000002,

		// 排除蓝牙网卡
		Exclude_BlueTeeth = 0x00000004,

		// 排除Microsoft Wi-Fi Direct Virtual Adapter
		Exclude_MicrosoftWifi = 0x00000008,

		// 
		Exclude_ZeroTier = 0x00000010,

	};

	// 设置排除列表
	static void  _SetExcludedList(std::vector<std::wstring>&list, uint32_t flag)
	{
		list.clear();

		if (flag & Exclude_BlueTeeth) {
			list.push_back(L"Bluetooth Device");
		}

		if (flag & Exclude_MicrosoftWifi) {
			list.push_back(L"Microsoft Wi-Fi");
		}
		

		if (flag & Exclude_Vmware) {
			list.push_back(L"VMware Virtual");
		}

		if (flag & Exclude_Loopback) {
			list.push_back(L"Software Loopback");
		}
		if (flag & Exclude_Loopback) {
			list.push_back(L"ZeroTier");
		}
	}

	// 设置全局排除列表
	static void  SetExcludedList(uint32_t flag = Exclude_Loopback | Exclude_Vmware | Exclude_BlueTeeth | Exclude_MicrosoftWifi)
	{
		_SetExcludedList(gExcludedList, flag);
	}

	/// 枚举网卡列表
	/// @param exclude_flag 在全局排除列表的基础上额外要排除的网卡
	void Enum(uint32_t exclude_flag);

	/// @brief 
	/// @param box 
	/// @param def 
	//void toComboBox(CComboBox* box, const std::wstring& def);

	const sAdapter* FindIp(uint32_t ip)
	{
		for (auto& i : d) {
			if (i.IpAddr.ip() == ip) {
				return &i;
			}
		}
		return nullptr;
	}

	const sAdapter* FindName(const std::wstring &name)
	{
		for (auto& i : d) {
			if (i.FriendlyName == name) {
				return &i;
			}
		}
		return nullptr;
	}

	const sAdapter* FindName(const std::string& name)
	{
		auto n = utf8_16(name);
		for (auto& i : d) {
			if (i.FriendlyName == n) {
				return &i;
			}
		}
		return nullptr;
	}

	sAdapter* operator [](uint32_t index) {
		if (index >= d.size()) return nullptr;
		return &d[index];
	}

	bool isUp(uint32_t index) {
		if (index >= d.size()) return false;
		return (d[index].OperStatus == IfOperStatusUp);
	}

	uint32_t size() const { return uint32_t(d.size()); }

	template<typename Func>
	void forEachAdapter(Func&& func) const {
		// 使用 const auto& 确保只读访问
		for (const auto& adapter : d) {
			func(adapter); // 调用传入的函数，传入 const sAdapter&
		}
	}
//protected:
	std::vector<sAdapter> d;
};


GDCPP_API int getIPFromHostname(const char* hostname, std::vector<ipv4addr>& foundIp);
#ifdef _AFXDLL
class CComboBox;
static inline void toComboBox(CAdapterList& list, CComboBox* box, const std::wstring& def)
{
	if (box == nullptr) return;

	for (int i = 0; i < list.d.size(); i++) {
		const auto& b = list.d[i].IpAddr.sin_addr.S_un.S_un_b;

		auto str = fmt::format(L"{}, {:03d}.{:03d}.{:03d}.{:03d}, {}"
			, list.d[i].OperStatus == IfOperStatusUp ? L"已连接" : L"未连接"
			, b.s_b1, b.s_b2, b.s_b3, b.s_b4
			, list.d[i].FriendlyName);

		auto index = box->AddString(str.c_str());
		box->SetItemData(index, i);
		if (list.d[i].FriendlyName == def) {
			box->SetCurSel(index);
		}
	}
}
#endif