#ifndef _FishIDE_Controls_h_
#define _FishIDE_Controls_h_

#include <CtrlLib/CtrlLib.h>

#include <Serial/Serial.h>

#include <MDNS/MDNS.h>

using namespace Upp;

#define LAYOUTFILE <FishIDE/FishIDEControls.lay>
#include <CtrlCore/lay.h>

/////////////////////////////////////////////////////////////////////////////////

class BoardCtrl : public WithBoardCtrlLayout<ParentCtrl>
{
	private:
	
	protected:
	
		// callbacks
		void dropCb(void);
		
		// selection
		void selCb(void);
		
		// options button menu
		void optionsCb(void);
		
		// options submenu
		void optionsSubMenu(Bar &bar, int curItem);

		// option menu
		void optionsMenu(Bar &bar);
	
	public:
	
		typedef BoardCtrl CLASSNAME;
	
		// constructor
		BoardCtrl();
		
		// destructor
		~BoardCtrl();
		
		Callback1<String> WhenBoard;
		
		BoardCtrl &Set(String const &board);
		String GetBoardName(void) const;
		
		void Refresh(void) { dropCb(); }
};

///////////////////////////////////////////////////////////////////////

class DeviceCtrl : public WithDeviceCtrlLayout<ParentCtrl>
{
	private:
	
		// network ports enabled
		bool _netEnabled;
	
		// last valid device
		String _lastDevice;
		
		// check if network device is responding
		bool checkNetDevice(IPV4Address &ip, int port);

	protected:
	
		// callbacks
		void dropCb(void);
		void pushCb(void);
		
		// selection
		void selCb(void);
		
	public:

		typedef DeviceCtrl CLASSNAME;
	
		// constructor
		DeviceCtrl();
		
		// destructor
		~DeviceCtrl();
		
		// enable/disable network ports
		DeviceCtrl &EnableNetwork(bool en = true);
		DeviceCtrl &DisableNetwork(void) { return EnableNetwork(false); }
		
		Callback1<String> WhenDevice;
		
		DeviceCtrl &Set(String const &device);
		String GetDevice(void) const;
		uint16_t GetNetworkPort(void) const;
		bool IsNetworkDevice(void) const;
		void refreshDevice(void);
};

/////////////////////////////////////////////////////////////////////////////////

class SendEdit : public LineEdit
{
	private:
		bool Key(dword key, int count)
		{
			WhenKey(key);
			if(key < 65536 && key != 8)
				return LineEdit::Key(key, count);
			else
				return true;
		}
		
		Image MouseEvent(int event, Point p, int zdelta, dword keyflags)
		{
			SetFocus();
			if(event == CURSORIMAGE)
				return LineEdit::MouseEvent(event, p, zdelta, keyflags);
			return Image();
		}
	
	public:
	
		Callback1<dword> WhenKey;
};

class SerialMonitorCtrl : public WithSerialMonitorLayout<ParentCtrl>
{
	private:
	
		DeviceCtrl deviceCtrl;

		Serial serial;
		
	protected:

		void openCb(void);
		void closeCb(void);
		void pollCb(void);
		void sendCb(dword key);
		void clearCb(void);
		
		enum {
			TIMEID_PERIODIC = ParentCtrl::TIMEID_COUNT,
			TIMEID_COUNT
		};
		
		void changeCb(void);
		void deviceCb(String const &dev);
		
	public:

		SendEdit sendEdit;
	
		typedef SerialMonitorCtrl CLASSNAME;
	
		// constructor
		SerialMonitorCtrl();
		
		// destructor
		~SerialMonitorCtrl();
		
		// streaming
		void Xmlize(XmlIO &xml);
		
		Callback WhenChange;
};

#endif
