/*
 * XFState.h
 *
 *  Created on: 23 nov. 2023
 *      Author: remi.heredero
 */

#ifndef XFSTATE_H_
#define XFSTATE_H_

#include "xf/interface/reactive.h"
#include "xf/interface/dispatcher.h"
#include "xf/eventstatus.h"
#include "xf/initialevent.h"
#include "xf/nulltransition.h"
#include "xf/timeout.h"
class XFBehavior;

#include <list>

class XFState {
	friend class XFBehavior;
public:

	/**
	 * Create and initialise a State for the behavior.
	 * Have to be initialized in the constructor of the behavior.
	 * @param behavior Pointer to the behavior class. Use the keyword this
	 */
	XFState(XFBehavior* behavior);
	~XFState() = default;

	/**
	 * Use for set next state of the Initial State.
	 * To be use only for stInitial.
	 * @param state Pointer to the next state
	 */
	inline void setNextState(XFState* state) { setNextState(XFEvent::Initial, XFEvent::XFEventType::Initial, state); };

	/**
	 * Set the conditional state of an custom event.
	 * @param evid Id of the event for set the next State
	 * @param state Pointer to the next state
	 */
	inline void setNextState(const int evid, XFState* state) { setNextState(evid, XFEvent::XFEventType::Event, state); };

	/**
	 * Set a new timer with a certain duration on every entry of this state.
	 * Set next state after
	 * @param time Time duration of the timeout
	 * @param nextState Pointer to the next state
	 */
	inline void setTimeout(int time, XFState* nextState) { setNextState(XFEvent::Timeout, time, XFEvent::XFEventType::Timeout, nextState); };

	/**
	 * Callback typedef
	 */
	typedef void (XFBehavior::*callback)(const XFEvent* ev);

	/**
	 * Register the method for the entry callback.
	 * @param cbEntry Callback automatically called when the state is onEntry
	 */
	inline void registerOnEntry(callback cbEntry) { cbEntry_ = cbEntry; };

	/**
	 * Register the method for the exit callback
	 * @param cbExit Callback automatically called when the state is onExit
	 */
	inline void registerOnExit(callback cbExit) { cbExit_ = cbExit; };

protected:
	inline void setNextState(const int evid, XFEvent::XFEventType type, XFState* state) {setNextState(evid, 0, type, state); };
	void setNextState(const int evid, const int time, XFEvent::XFEventType type, XFState* state);

	XFEventStatus onState(const XFEvent* ev);
	void onEntry(const XFEvent* ev);
	void onExit(const XFEvent* ev);

protected:
	XFBehavior* const pBehavior;
	typedef struct {
		int evid;
		int time;
		XFEvent::XFEventType evType;
		XFState* nextState;
	} transition;
	std::list<transition> transitions_;

	callback cbEntry_;
	callback cbExit_;

};

#endif /* XFSTATE_H_ */
