//..............................................................................
//
// $(pluginName) plugin
//

import "doc_Plugin.jnc"

//..............................................................................

class $(sessionClass): doc.Session
{
protected:
	enum State
	{
		Closed,
		Connected,
	}

	static char const* m_stateStringTable [] =
	{
		"Closed",
		"Connected",
	};

	enum ActionId
	{
		Connect,
		_Count,
	}

	enum IconId
	{
		Connect,
		Disconnect,
		_Count,
	}

	enum StatusPaneId
	{
		Address,
		State,
		_Count,
	}

protected:

	// transport

	State bindable m_state;
	char const* m_address;

	// toolbar, status bar & menu

	gui.Action* m_actionTable [ActionId._Count];
	gui.Icon* m_iconTable [IconId._Count];
	gui.StatusPane* m_statusPaneTable [StatusPaneId._Count];
	gui.ComboBox* m_addressCombo;

	// property grid

	gui.StringProperty* m_addressProp;

public:
	construct (doc.PluginHost* pluginHost);

	bool connect () throws;
	disconnect ();

	override void load (doc.Storage* storage);
	override void save (doc.Storage* storage);
	override void updateProperties ();
	override bool applyProperties () throws;
	override void restoreDefaultProperties ();

	override size_t transmit (
		void const* p,
		size_t size
		) throws;

protected:
	onConnect ();

	createUi ();
	reactor m_uiReactor ();
}

// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

$(sessionClass).construct (doc.PluginHost* pluginHost)
{
	basetype.construct (pluginHost);

	pluginHost.m_log.m_representerFunc = $(logRepresenterFunc);
	m_state = State.Closed;
	createUi ();
}

$(sessionClass).createUi ()
{
	// toolbar

	m_pluginHost.m_toolBar.addLabel ("Address:");
	m_addressCombo = m_pluginHost.m_toolBar.addComboBox (-1);
	m_addressCombo.m_isEditable = true;
	m_addressCombo.m_onEnter += connect;

	m_iconTable [IconId.Connect] = new gui.Icon ("images/connect.png");
	m_iconTable [IconId.Disconnect] = new gui.Icon ("images/disconnect.png");

	m_actionTable [ActionId.Connect] = createAction ("Connect", m_iconTable [IconId.Connect]);
	m_actionTable [ActionId.Connect].m_onTriggered += onConnect;

	// status bar

	m_statusPaneTable [StatusPaneId.Address] = m_pluginHost.m_statusBar.addPane (, 100);
	m_statusPaneTable [StatusPaneId.Address].m_color = gui.StdColor.Blue;
	m_statusPaneTable [StatusPaneId.State] = m_pluginHost.m_statusBar.addPane (, 80);

	// property grid

	m_addressProp = m_pluginHost.m_propertyGrid.createStringProperty (
		"Remote address",
		"Remote address to connect to"
		);

	m_uiReactor.start ();
}

$(sessionClass).onConnect ()
{
	if (m_state)
		disconnect ();
	else
		try	connect ();
}

bool $(sessionClass).connect () throws
{
	disconnect ();

	char const* address = m_addressCombo.m_editText;
	m_addressCombo.addEditTextToHistory ();

	writeLog ($(logRecordCodeEnum).Connected, address, strlen (address));
	m_address = strdup (address);
	m_state = State.Connected;
	return true;
}

$(sessionClass).disconnect ()
{
	if (!m_state)
		return;

	writeLog ($(logRecordCodeEnum).Disconnected, m_address, strlen (m_address));
	m_state = State.Closed;
}

void $(sessionClass).load (doc.Storage* storage)
{
	m_addressCombo.m_editText = storage.readString ("address");
}

void $(sessionClass).save (doc.Storage* storage)
{
	storage.writeString ("address", m_addressCombo.m_editText);
}

void $(sessionClass).updateProperties ()
{
	m_addressProp.m_value = m_addressCombo.m_editText;
}

bool $(sessionClass).applyProperties () throws
{
	m_addressCombo.m_editText = m_addressProp.m_value;
	return true;
}

void $(sessionClass).restoreDefaultProperties ()
{
	m_addressProp.m_value = "remote-address";
}

size_t $(sessionClass).transmit (
	void const* p,
	size_t size
	) throws
{
	if (m_state != State.Connected)
		return -1;

	writeLog (log.StdRecordCode.Tx, p, size);
	return size;
}

reactor $(sessionClass).m_uiReactor ()
{
	m_title = $"$(pluginName) $(m_addressCombo.m_editText)";
	m_isTransmitEnabled = m_state == State.Connected;
	m_actionTable [ActionId.Connect].m_text = m_state ? "Disconnect" : "Connect";
	m_actionTable [ActionId.Connect].m_icon = m_iconTable [m_state ? IconId.Disconnect : IconId.Connect];
	m_statusPaneTable [StatusPaneId.State].m_text = m_stateStringTable [m_state];
	m_statusPaneTable [StatusPaneId.Address].m_text = m_state == State.Connected ? m_address : null;
	m_statusPaneTable [StatusPaneId.Address].m_isVisible = m_state == State.Connected;
}

//..............................................................................
