#pragma once

#include "FlowSshNetIncludes.h"
#include "FlowSshNetUtils.h"



namespace Bitvise {
namespace FlowSshNet {


// ProgressHandlerCpp

ref class ProgressHandler;
class ProgressHandlerCpp : public FlowSshCpp::ProgressHandler
{
private:
	// This object must be created on the heap.
	virtual ~ProgressHandlerCpp() {}

public:
	ProgressHandlerCpp(FlowSshNet::ProgressHandler^ flowSshNet)
		: m_flowSshNet_weak(flowSshNet)
		, m_flowSshNetDisposed(false) {}
	void FlowSshNetDisposed() { m_flowSshNetDisposed = true; }
	void OnStartFailed() { m_flowSshNet.ReleaseTarget(); }

protected:
	virtual void OnStart();
	virtual void OnDone();
	virtual void OnProgress(unsigned int taskSpecificStep);
	virtual void OnSuccess();
	virtual void OnError(unsigned int taskSpecificStep, std::wstring const& auxInfo);

private:
	bvgcroot<FlowSshNet::ProgressHandler^>::normal m_flowSshNet;
	bvgcroot<FlowSshNet::ProgressHandler^>::weak   m_flowSshNet_weak;
	volatile bool m_flowSshNetDisposed;
};


// ForwardingHandlerCpp

ref class ForwardingHandler;
class ForwardingHandlerCpp : public FlowSshCpp::ForwardingHandler
{
private:
	// This object must be created on the heap.
	virtual ~ForwardingHandlerCpp() {}

public:
	ForwardingHandlerCpp(FlowSshNet::ForwardingHandler^ flowSshNet)
		: m_flowSshNet_weak(flowSshNet)
		, m_flowSshNetDisposed(false) {}
	void FlowSshNetDisposed() { m_flowSshNetDisposed = true; }
	void OnStartFailed() { m_flowSshNet.ReleaseTarget(); }

protected:
	virtual void OnStart();
	virtual void OnDone();
	virtual void OnSuccess(unsigned int listPort);
	virtual void OnError(FlowSshCpp::ForwardingErr const& error);

private:
	bvgcroot<FlowSshNet::ForwardingHandler^>::normal m_flowSshNet;
	bvgcroot<FlowSshNet::ForwardingHandler^>::weak   m_flowSshNet_weak;
	volatile bool m_flowSshNetDisposed;
};


// ClientCpp

ref class ClientBase;
class ClientCpp : public FlowSshCpp::Client
{
private:
	// This object must be created on the heap.
	virtual ~ClientCpp() {}

public:
	ClientCpp(FlowSshNet::ClientBase^ flowSshNet)
		: m_flowSshNet_weak(flowSshNet)
		, m_flowSshNetDisposed(false) {}
	void FlowSshNetDisposed() { m_flowSshNetDisposed = true; }

protected:
	void OnSshVersion(std::wstring const& version);
	bool OnHostKey(FlowSshCpp::RefPtr<FlowSshCpp::PublicKey> publicKey);
	void OnKexDone(unsigned __int64 kexNr, bool incoming, std::wstring const& kexAlg, std::wstring const& encAlg, std::wstring const& macAlg, std::wstring const& cmprAlg);
	bool OnFurtherAuth(FlowSshCpp::Client::FurtherAuth& furtherAuth);
	bool OnPasswordChange(FlowSshCpp::Client::PasswordChange& passwordChange);
	void OnBanner(std::wstring const& banner);
	void OnSessionIdReply(unsigned int code);
	void OnServerNotice(unsigned int severity, std::wstring const& facility, std::wstring const& status, std::wstring const& description);
	bool OnHostKeySync(FlowSshCpp::RefPtr<FlowSshCpp::PublicKey> publicKey, bool keyVerified);
	void OnForwardingLog(FlowSshCpp::RefPtrConst<FlowSshCpp::ForwardingLog> const& log);
	void OnDisconnect(unsigned int reason, std::wstring const& desc);

private:
	bvgcroot<FlowSshNet::ClientBase^>::weak m_flowSshNet_weak;
	volatile bool m_flowSshNetDisposed;
};


// ReceiveHandlerCpp

ref class ReceiveHandler;
class ReceiveHandlerCpp : public FlowSshCpp::ReceiveHandler
{
private:
	// This object must be created on the heap.
	virtual ~ReceiveHandlerCpp() {}

public:
	ReceiveHandlerCpp(FlowSshNet::ReceiveHandler^ flowSshNet)
		: m_flowSshNet_weak(flowSshNet)
		, m_flowSshNetDisposed(false) {}
	void FlowSshNetDisposed() { m_flowSshNetDisposed = true; }
	void OnStartFailed() { m_flowSshNet.ReleaseTarget(); }

protected:
	virtual void OnStart();
	virtual void OnDone();
	virtual void OnReceive(bool stdErr, unsigned char const* dataPtr, unsigned int dataSize, bool eof);
	virtual void OnError();

private:
	bvgcroot<FlowSshNet::ReceiveHandler^>::normal m_flowSshNet;
	bvgcroot<FlowSshNet::ReceiveHandler^>::weak   m_flowSshNet_weak;
	volatile bool m_flowSshNetDisposed;
};


// ClientSessionChannelCpp

ref class ClientSessionChannel;
class ClientSessionChannelCpp : public FlowSshCpp::ClientSessionChannel
{
private:
	// This object must be created on the heap.
	virtual ~ClientSessionChannelCpp() {}

public:
	ClientSessionChannelCpp(FlowSshCpp::RefPtrConst<FlowSshCpp::Client> const& client, FlowSshNet::ClientSessionChannel^ flowSshNet)
		: FlowSshCpp::ClientSessionChannel(client)
		, m_flowSshNet_weak(flowSshNet)
		, m_flowSshNetDisposed(false) {}
	void FlowSshNetDisposed() { m_flowSshNetDisposed = true; }

protected:
	virtual void OnExitStatus(FlowSshC_ExitStatus const& status);
	virtual void OnExitSignal(ExitSignal const& signal);
	virtual void OnChannelClose();

private:
	bvgcroot<FlowSshNet::ClientSessionChannel^>::weak m_flowSshNet_weak;
	volatile bool m_flowSshNetDisposed;
};


// RealPathHandlerCpp

ref class RealPathHandler;
class RealPathHandlerCpp : public FlowSshCpp::RealPathHandler
{
private:
	// This object must be created on the heap.
	virtual ~RealPathHandlerCpp() {}

public:
	RealPathHandlerCpp(FlowSshNet::RealPathHandler^ flowSshNet) 
		: m_flowSshNet_weak(flowSshNet)
		, m_flowSshNetDisposed(false) {}
	void FlowSshNetDisposed() { m_flowSshNetDisposed = true; }
	void OnStartFailed() { m_flowSshNet.ReleaseTarget(); }

protected:
	virtual void OnStart();
	virtual void OnDone();
	virtual void OnRealPath(std::wstring const& realPath);
	virtual void OnError(FlowSshCpp::SftpErr const& error);

private:
	bvgcroot<FlowSshNet::RealPathHandler^>::normal m_flowSshNet;
	bvgcroot<FlowSshNet::RealPathHandler^>::weak   m_flowSshNet_weak;
	volatile bool m_flowSshNetDisposed;
};


// StatHandlerCpp

ref class StatHandler;
class StatHandlerCpp : public FlowSshCpp::StatHandler
{
protected:
	// This object must be created on the heap.
	virtual ~StatHandlerCpp() {}

public:
	StatHandlerCpp(FlowSshNet::StatHandler^ flowSshNet)
		: m_flowSshNet_weak(flowSshNet)
		, m_flowSshNetDisposed(false) {}
	void FlowSshNetDisposed() { m_flowSshNetDisposed = true; }
	void OnStartFailed() { m_flowSshNet.ReleaseTarget(); }

protected:
	virtual void OnStart();
	virtual void OnDone();
	virtual void OnStat(FlowSshCpp::FileAttrs const& fileAttrs);
	virtual void OnError(FlowSshCpp::SftpErr const& error);

private:
	bvgcroot<FlowSshNet::StatHandler^>::normal m_flowSshNet;
	bvgcroot<FlowSshNet::StatHandler^>::weak   m_flowSshNet_weak;
	volatile bool m_flowSshNetDisposed;
};


// SftpHandlerCpp

ref class SftpHandler;
class SftpHandlerCpp : public FlowSshCpp::SftpHandler
{
protected:
	// This object must be created on the heap.
	virtual ~SftpHandlerCpp() {}

public:
	SftpHandlerCpp(FlowSshNet::SftpHandler^ flowSshNet)
		: m_flowSshNet_weak(flowSshNet)
		, m_flowSshNetDisposed(false) {}
	void FlowSshNetDisposed() { m_flowSshNetDisposed = true; }
	void OnStartFailed() { m_flowSshNet.ReleaseTarget(); }

protected:
	virtual void OnStart();
	virtual void OnDone();
	virtual void OnSuccess();
	virtual void OnError(FlowSshCpp::SftpErr const& error);

private:
	bvgcroot<FlowSshNet::SftpHandler^>::normal m_flowSshNet;
	bvgcroot<FlowSshNet::SftpHandler^>::weak   m_flowSshNet_weak;
	volatile bool m_flowSshNetDisposed;
};


// ListHandlerCpp

ref class ListHandler;
class ListHandlerCpp : public FlowSshCpp::ListHandler
{
protected:
	// This object must be created on the heap.
	virtual ~ListHandlerCpp() {}

public:
	ListHandlerCpp(FlowSshNet::ListHandler^ flowSshNet)
		: m_flowSshNet_weak(flowSshNet)
		, m_flowSshNetDisposed(false) {}
	void FlowSshNetDisposed() { m_flowSshNetDisposed = true; }
	void OnStartFailed() { m_flowSshNet.ReleaseTarget(); }

protected:
	virtual void OnStart();
	virtual void OnDone();
	virtual bool OnList(std::vector<FlowSshCpp::FileInfo> const& fileInfos, bool endOfList);
	virtual void OnError(FlowSshCpp::ListErr const& error);

private:
	bvgcroot<FlowSshNet::ListHandler^>::normal m_flowSshNet;
	bvgcroot<FlowSshNet::ListHandler^>::weak   m_flowSshNet_weak;
	volatile bool m_flowSshNetDisposed;
};


// TransferHandlerCpp

ref class TransferHandler;
class TransferHandlerCpp : public FlowSshCpp::TransferHandler
{
protected:
	// This object must be created on the heap.
	virtual ~TransferHandlerCpp() {}

public:
	TransferHandlerCpp(FlowSshNet::TransferHandler^ flowSshNet)
		: m_flowSshNet_weak(flowSshNet)
		, m_flowSshNetDisposed(false) {}
	void FlowSshNetDisposed() { m_flowSshNetDisposed = true; }
	void OnStartFailed() { m_flowSshNet.ReleaseTarget(); }

protected:
	virtual void OnStart();
	virtual void OnDone();
	virtual bool OnTransfer(bool done, FlowSshC_TransferStat const& transferStat);
	virtual void OnError(FlowSshCpp::TransferErr const& error);

private:
	bvgcroot<FlowSshNet::TransferHandler^>::normal m_flowSshNet;
	bvgcroot<FlowSshNet::TransferHandler^>::weak   m_flowSshNet_weak;
	volatile bool m_flowSshNetDisposed;
};


// ClientSftpChannelCpp

ref class ClientSftpChannel;
class ClientSftpChannelCpp : public FlowSshCpp::ClientSftpChannel
{
protected:
	// This object must be created on the heap.
	virtual ~ClientSftpChannelCpp() {}

public:
	ClientSftpChannelCpp(FlowSshCpp::RefPtrConst<FlowSshCpp::Client> const& client, FlowSshNet::ClientSftpChannel^ flowSshNet)
		: FlowSshCpp::ClientSftpChannel(client)
		, m_flowSshNet_weak(flowSshNet)
		, m_flowSshNetDisposed(false) {}
	void FlowSshNetDisposed() { m_flowSshNetDisposed = true; }

protected:
	virtual void OnSftpVersion(unsigned int version);
	virtual void OnChannelClose();

private:
	bvgcroot<FlowSshNet::ClientSftpChannel^>::weak m_flowSshNet_weak;
	volatile bool m_flowSshNetDisposed;
};


} // namespace FlowSshNet
} // namespace Bitvise