#pragma once

#include "data/command/InertiaCommand.h"

namespace inertia
{

enum SchedulerCommands : uint8_t {
	SchedulerCommandTimedEvent = 0,
	SchedulerCommandChannelAction = 1
};


enum SchedulerTimedEventCommands : uint8_t {
	SchedulerTimedEventAddItem = 0,
	SchedulerTimedEventGetAll = 1,
	SchedulerTimedEventGetLast = 2,
	SchedulerTimedEventGetNext = 3,
	SchedulerTimedEventClear = 4
};


enum SchedulerChannelActionCommands : uint8_t {
	SchedulerChannelActionAddChannel = 0,
	SchedulerChannelActionGetChannel = 1,
	SchedulerChannelActionGetActive = 2,
	SchedulerChannelActionDeleteChannel = 3,
	SchedulerChannelActionGetChannelList = 4,
	SchedulerChannelActionClear = 5
};


enum SchedulerTimedEventRecurrence : uint8_t {
	SchedulerTimedEventSingle = 0,
	SchedulerTimedEventMinute,
	SchedulerTimedEventHour,
	SchedulerTimedEventDay,
	SchedulerTimedEventWeek,
	SchedulerTimedEventMonth,
	SchedulerTimedEventYear
};


struct INERTIA_API TimedEvent
{
	SchedulerTimedEventRecurrence intervalRecurrence;
	uint8_t interval;
	uint32_t firstEventTimestamp;
	uint32_t lastEventTimestamp;
	uint8_t eventChannel;

	TimedEvent();
	TimedEvent(const uint8_t* packet, const unsigned max_size);
	TimedEvent(std::wstring const& argString);

	void GetBytes(std::vector<uint8_t>& out) const;
	const std::wstring ToString() const;

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif
};


struct INERTIA_API ChannelAction
{
	bool preserveAction;
	uint8_t channelNumber;
	uint32_t timeOffset;
	uint16_t addressTo;
	uint16_t addressFrom;
	std::wstring name;
	std::vector<uint8_t> action;

	ChannelAction();
	ChannelAction(const uint8_t* packet, const unsigned max_size);
	ChannelAction(std::wstring const& argString);

	void GetBytes(std::vector<uint8_t>& out) const;
	const std::wstring ToString() const;

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif
};


struct INERTIA_API SchedulerCommand
	: InertiaCommand
{
protected:
	SchedulerCommand(uint8_t subType);
	SchedulerCommand(const uint8_t* packet, const unsigned max_size);
	SchedulerCommand(std::wstring const& argString);

	uint8_t subType;

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif

public:
	InertiaCommandGroups GetGroup() const override;

	static InertiaCommandPtr Parse(const uint8_t* in, unsigned const packetSize);
	static InertiaCommandPtr Parse(std::wstring const& argString);
};


struct INERTIA_API SchedulerTimedEventRequest
	: SchedulerCommand
{
protected:
	SchedulerTimedEventRequest(uint8_t subType);
	SchedulerTimedEventRequest(const uint8_t* packet, const unsigned max_size);
	SchedulerTimedEventRequest(std::wstring const& argString);

	uint8_t GetType() const override;
	bool IsResponse() const override;
};


struct INERTIA_API SchedulerTimedEventResponse
	: SchedulerCommand
{
protected:
	SchedulerTimedEventResponse(const uint8_t* packet, const unsigned max_size);
	SchedulerTimedEventResponse(std::wstring const& argString);

	uint8_t GetType() const override;
	bool IsResponse() const override;
};


struct INERTIA_API SchedulerTimedEventAddItemRequest
	: SchedulerTimedEventRequest
{
	TimedEvent timedEvent;

	SchedulerTimedEventAddItemRequest();
	SchedulerTimedEventAddItemRequest(const uint8_t* packet, const unsigned max_size);
	SchedulerTimedEventAddItemRequest(std::wstring const& argString);

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif
};


struct INERTIA_API SchedulerTimedEventAddItemResponse
	: SchedulerTimedEventResponse
	, BoolValue
{
	SchedulerTimedEventAddItemResponse(const uint8_t* packet, const unsigned max_size);
	SchedulerTimedEventAddItemResponse(std::wstring const& argString);

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif
};


struct INERTIA_API SchedulerTimedEventGetAllRequest
	: SchedulerTimedEventRequest
{
	SchedulerTimedEventGetAllRequest();
	SchedulerTimedEventGetAllRequest(const uint8_t* packet, const unsigned max_size);
	SchedulerTimedEventGetAllRequest(std::wstring const& argString);

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif
};


struct INERTIA_API SchedulerTimedEventGetAllResponse
	: SchedulerTimedEventResponse
{
protected:
	uint8_t batchNumber;
public:
	std::vector<TimedEvent> timedEvents;

	SchedulerTimedEventGetAllResponse(const uint8_t* packet, const unsigned max_size);
	SchedulerTimedEventGetAllResponse(std::wstring const& argString);

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif
};


struct INERTIA_API SchedulerTimedEventGetLastRequest
	: SchedulerTimedEventRequest
{
	SchedulerTimedEventGetLastRequest();
	SchedulerTimedEventGetLastRequest(const uint8_t* packet, const unsigned max_size);
	SchedulerTimedEventGetLastRequest(std::wstring const& argString);

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif
};


struct INERTIA_API SchedulerTimedEventGetLastResponse
	: SchedulerTimedEventResponse
{
protected:
	bool hasItem;

public:
	TimedEvent timedEvent;

	SchedulerTimedEventGetLastResponse(const uint8_t* packet, const unsigned max_size);
	SchedulerTimedEventGetLastResponse(std::wstring const& argString);

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif
};


struct INERTIA_API SchedulerTimedEventGetNextRequest
	: SchedulerTimedEventRequest
{
	SchedulerTimedEventGetNextRequest();
	SchedulerTimedEventGetNextRequest(const uint8_t* packet, const unsigned max_size);
	SchedulerTimedEventGetNextRequest(std::wstring const& argString);

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif
};


struct INERTIA_API SchedulerTimedEventGetNextResponse
	: SchedulerTimedEventResponse
{
protected:
	bool hasItem;

public:
	TimedEvent timedEvent;

	SchedulerTimedEventGetNextResponse(const uint8_t* packet, const unsigned max_size);
	SchedulerTimedEventGetNextResponse(std::wstring const& argString);

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif
};


struct INERTIA_API SchedulerTimedEventClearRequest
	: SchedulerTimedEventRequest
{
	SchedulerTimedEventClearRequest();
	SchedulerTimedEventClearRequest(const uint8_t* packet, const unsigned max_size);
	SchedulerTimedEventClearRequest(std::wstring const& argString);

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif
};


struct INERTIA_API SchedulerTimedEventClearResponse
	: SchedulerTimedEventResponse
	, BoolValue
{
	SchedulerTimedEventClearResponse(const uint8_t* packet, const unsigned max_size);
	SchedulerTimedEventClearResponse(std::wstring const& argString);

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif
};


struct INERTIA_API SchedulerActionRequest
	: SchedulerCommand
{
protected:
	SchedulerActionRequest(uint8_t subType);
	SchedulerActionRequest(const uint8_t* packet, const unsigned max_size);
	SchedulerActionRequest(std::wstring const& argString);

	uint8_t GetType() const override;
	bool IsResponse() const override;
};


struct INERTIA_API SchedulerActionResponse
	: SchedulerCommand
{
protected:
	SchedulerActionResponse(const uint8_t* packet, const unsigned max_size);
	SchedulerActionResponse(std::wstring const& argString);

	uint8_t GetType() const override;
	bool IsResponse() const override;
};


struct INERTIA_API SchedulerActionAddChannelRequest
	: SchedulerActionRequest
{
	ChannelAction channelAction;

	SchedulerActionAddChannelRequest();
	SchedulerActionAddChannelRequest(const uint8_t* packet, const unsigned max_size);
	SchedulerActionAddChannelRequest(std::wstring const& argString);

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif
};


struct INERTIA_API SchedulerActionAddChannelResponse
	: SchedulerActionResponse
	, BoolValue
{
	SchedulerActionAddChannelResponse(const uint8_t* packet, const unsigned max_size);
	SchedulerActionAddChannelResponse(std::wstring const& argString);

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif
};


struct INERTIA_API SchedulerActionGetChannelRequest
	: SchedulerActionRequest
{
	uint8_t channelNumber;

	SchedulerActionGetChannelRequest();
	SchedulerActionGetChannelRequest(const uint8_t* packet, const unsigned max_size);
	SchedulerActionGetChannelRequest(std::wstring const& argString);

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif
};


struct INERTIA_API SchedulerActionGetChannelResponse
	: SchedulerActionResponse
{
protected:
	uint8_t batchNumber;
public:
	std::vector<ChannelAction> channelActions;

	SchedulerActionGetChannelResponse(const uint8_t* packet, const unsigned max_size);
	SchedulerActionGetChannelResponse(std::wstring const& argString);

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif
};


struct INERTIA_API SchedulerActionGetActiveChannelRequest
	: SchedulerActionRequest
{
	SchedulerActionGetActiveChannelRequest();
	SchedulerActionGetActiveChannelRequest(const uint8_t* packet, const unsigned max_size);
	SchedulerActionGetActiveChannelRequest(std::wstring const& argString);

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif
};


struct INERTIA_API SchedulerActionGetActiveChannelResponse
	: SchedulerActionResponse
{
protected:
	uint8_t batchNumber;
public:
	std::vector<uint8_t> channelData;

	SchedulerActionGetActiveChannelResponse(const uint8_t* packet, const unsigned max_size);
	SchedulerActionGetActiveChannelResponse(std::wstring const& argString);

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif
};


struct INERTIA_API SchedulerActionDeleteChannelRequest
	: SchedulerActionRequest
{
	uint8_t channelNumber;

	SchedulerActionDeleteChannelRequest();
	SchedulerActionDeleteChannelRequest(const uint8_t* packet, const unsigned max_size);
	SchedulerActionDeleteChannelRequest(std::wstring const& argString);

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif
};


struct INERTIA_API SchedulerActionDeleteChannelResponse
	: SchedulerActionResponse
	, BoolValue
{
	SchedulerActionDeleteChannelResponse(const uint8_t* packet, const unsigned max_size);
	SchedulerActionDeleteChannelResponse(std::wstring const& argString);

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif
};


struct INERTIA_API SchedulerActionGetChannelListRequest
	: SchedulerActionRequest
{
	SchedulerActionGetChannelListRequest();
	SchedulerActionGetChannelListRequest(const uint8_t* packet, const unsigned max_size);
	SchedulerActionGetChannelListRequest(std::wstring const& argString);

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif
};


struct INERTIA_API SchedulerActionGetChannelListResponse
	: SchedulerActionResponse
{
public:
	std::vector<uint8_t> channelNumbers;

	SchedulerActionGetChannelListResponse(const uint8_t* packet, const unsigned max_size);
	SchedulerActionGetChannelListResponse(std::wstring const& argString);

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif
};


struct INERTIA_API SchedulerActionClearRequest
	: SchedulerActionRequest
{
	SchedulerActionClearRequest();
	SchedulerActionClearRequest(const uint8_t* packet, const unsigned max_size);
	SchedulerActionClearRequest(std::wstring const& argString);

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif
};


struct INERTIA_API SchedulerActionClearResponse
	: SchedulerActionResponse
	, BoolValue
{
	SchedulerActionClearResponse(const uint8_t* packet, const unsigned max_size);
	SchedulerActionClearResponse(std::wstring const& argString);

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif
};

}
