/*
 * 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;

	/**
	 * 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 addTransition(const int evid, XFState* state) { addTransition(XFEvent::XFEventType::Event, evid, 0, 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) { addTransition(XFEvent::XFEventType::Timeout, XFEvent::Timeout, time, nextState); };

	// Callback typedef for callback without parameter
	typedef void (XFBehavior::*callback)();

	//inline void registerOnState(callback cbState) { cbState_ = cbState; };

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

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


	//Callback typedef for callback with event in parameter
	typedef void (XFBehavior::*callbackEv)(const XFEvent* ev);

	//inline void registerOnState(callbackEv cbState) { cbEvState_ = cbState; };

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

	/**
	 * Register the method for the exit callback with event in parameter
	 * @param cbExit Callback automatically called when the state is onExit
	 */
	inline void registerOnExit(callbackEv cbExit) { cbEvExit_ = cbExit; };

protected:
	void addTransition(XFEvent::XFEventType type, const int evid, const int time, XFState* state);

	XFEventStatus changeState(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 cbState_;
	callback cbEntry_;
	callback cbExit_;
	callbackEv cbEvState_;
	callbackEv cbEvEntry_;
	callbackEv cbEvExit_;

};


class XFInitialState : public XFState {
public:
	/**
	 * Use for set next state of the Initial State.
	 * @param state Pointer to the next state
	 */
	inline XFInitialState(XFBehavior* behavior) : XFState(behavior) {};
	~XFInitialState() = default;
	inline void addInitialTransition(XFState* state) { addTransition(XFEvent::XFEventType::Initial, XFEvent::Initial, 0, state); };
};
#endif /* XFSTATE_H_ */
