#ifndef __BOCHS_LISTENER_AH__
  #define __BOCHS_LISTENER_AH__

#include "config/VariantConfig.hpp"
#include "config/FailConfig.hpp"

#if defined(BUILD_BOCHS)

#include <cassert>
#include "bochs.h"
#include "BochsListener.hpp"

/*
 * Note: A (Fail)Bochs bug currently leads to the consequence that timers
 * cannot be added/enabled at boot time (see BochsController.hpp for further
 * details).
 */
aspect BochsListener {
	advice "fail::TimerListener" : slice class {
	public:
		bool onAddition()
		{
			// Register the timer listener in the Bochs simulator:
			timer_id_t id = m_registerTimer(this);
			if (id == -1) {
				setId(INVALID_TIMER);
				return false; // unable to register the timer (error in Bochs' function call)
			}
			setId(id);
			return true;
		}
		void onDeletion()
		{
			// Unregister the time listener:
			m_unregisterTimer(this);
		}
	private:
		timer_id_t m_registerTimer(TimerListener* pev)
		{
			assert(pev != NULL && "FATAL ERROR: TimerListener object ptr cannot be NULL!");
			return static_cast<timer_id_t>(
				bx_pc_system.register_timer(pev, fail::onTimerTrigger,
				    pev->getTimeout() /*timeout in microseconds*/,
				    false /*non-continuous*/,
				    true /*start immediately*/, "Fail*: BochsController"/*name*/));
		}
		bool m_unregisterTimer(TimerListener* pev)
		{
			assert(pev != NULL && "FATAL ERROR: TimerListener object ptr cannot be NULL!");
			bx_pc_system.deactivate_timer(static_cast<unsigned>(pev->getId()));
			return bx_pc_system.unregisterTimer(static_cast<unsigned>(pev->getId()));
		}
	};
};

#endif // BUILD_BOCHS && CONFIG_EVENT_BREAKPOINTS
#endif // __BOCHS_LISTENER_AH__
