
#pragma once

#include <atlbase.h>
#include <dplay.h>
#include <dplobby.h>
#include <string>
#include <list>

class Fibres {
public:
	// 
	enum State {
		stateNo,
		stateListen,
		stategone,
	};
	// 
	enum ResultID {
		resiNo,
		resiTransit,
	};
	// 
	struct RES {
		ResultID resi;
		bool ok;
		std::string buff;

		RES() {
			ok = false;
			resi = resiNo;
		}
	};

	// 
	State state;
	// 
	CComPtr<IDirectPlay4A> pDP;
	CComPtr<IDirectPlayLobby3A> pDPL;
	DPID dpidMe;
	GUID guidInst;
	std::list<RES> reses;

	// 
	Fibres()
	{
		state = stateNo;
	}
	// 
	bool createInetAddr(LPCSTR psz, BYTE *buff, DWORD buffSize)
	{
		// {36E95EE0-8577-11CF-960C-0080C7534E82},DirectPlay インターネット TCP/IP 接続
		GUID _DPSPID_IP;
		memcpy(&_DPSPID_IP, "\xE0\x5E\xE9\x36\x77\x85\xCF\x11\x96\x0C\x00\x80\xC7\x53\x4E\x82", 16);

		HRESULT hr = pDPL->CreateAddress(_DPSPID_IP, DPAID_INet, psz, strlen(psz), buff, &buffSize);
		if (FAILED(hr))
			return false;

		return true;
	}
	// 
	bool construct(bool server = true);
	bool receiver();
	void close();

	bool serverNow();
	bool connectNow();
	bool exec();

	bool simpleOrder(DWORD order);
	bool sendSettleSave(BYTE *buff, DWORD buffSize);

	bool isActive()
	{
		return pDP != NULL;
	}

protected:
	// 
	static BOOL FAR PASCAL fn(
		LPCDPSESSIONDESC2 lpThisSD,
		LPDWORD lpdwTimeOut,
		DWORD dwFlags,
		LPVOID lpContext
		)
	{
		return reinterpret_cast<Fibres *>(lpContext)->fn(lpThisSD, lpdwTimeOut, dwFlags);
	}
	// 
	bool fn(LPCDPSESSIONDESC2 pdpsd, LPDWORD lpdwTimeOut, DWORD dwFlags);
};

extern Fibres fibres;
