/** SGX

The   sss    gggg x   x   
     s      g      x x    Engine
      sss   g  gg   x
         s  g   g  x x          Copyright 1995-2009.
     ssss    gggg x   x         Steven Goodwin. All Rights Reserved.
    
This version has been released under the GNU Public License v2.0.

Please see the license files for details.

File: sgx/src/sgx/input/rumble_device.cpp

*/

#include "sgx/core/core.hpp"
#include "sgx/input/input.hpp"

CSGXRumbleDevice::CSGXRumbleDevice() {
	m_bMute= FALSE;
	m_bSuspend = FALSE;
	m_vFromPosition.zero();
} 

void CSGXRumbleDevice::mute() {
	m_bMute= TRUE;
}

void CSGXRumbleDevice::unmute() {
	 m_bMute = FALSE;
}

void CSGXRumbleDevice::enable(const tBOOL enable) {
	 m_bMute = !enable;
}

void CSGXRumbleDevice::suspend(const tBOOL suspend) {
	 m_bSuspend = suspend;
}

void CSGXRumbleDevice::setFromPosition(const sgxVector3 &vPosition) {
	 m_vFromPosition= vPosition;
}

void CSGXRumbleDevice::getFromPosition(sgxVector3 &vPosition) const {
	 vPosition = m_vFromPosition;
}

tBOOL CSGXRumbleDevice::isMute() const {
	return m_bMute;
}

void CSGXRumbleDevice::update(const tREAL32 telaps) {
	tREAL32 intensity = 0;

	if (!m_bSuspend) {
		for(int i=0;i<MAX_RUMBLES;++i) {
			m_RumbleStateList[i].update(telaps);
		}
	
		if (!m_bMute) {
			for(int i=0;i<MAX_RUMBLES;++i) {
				intensity += m_RumbleStateList[i].getIntensity(m_vFromPosition);
			}
		}
	}
	
	setRumbleIntensity(intensity);
}

void CSGXRumbleDevice::setRumbleIntensity(const tREAL32 intensity) {
	m_fCurrentIntensity = intensity;
}

tREAL32		
CSGXRumbleDevice::getCurrentIntensity() const {
	return m_fCurrentIntensity;
}

void CSGXRumbleDevice::stopRumble(const tUINT32 handle) {
	if (handle >=0 && handle < MAX_RUMBLES) {
		m_RumbleStateList[handle].stop();
	}
}

void CSGXRumbleDevice::stopAllRumbles() {
	for(int i=0;i<MAX_RUMBLES;++i) {
		m_RumbleStateList[i].stop();
	}
}


tUINT32 CSGXRumbleDevice::playRumble(const CSGXRumbleProfile *pProfile, const tREAL32 fStrength, const tREAL32 fDuration) {
	tUINT32 id = getNewRumbleHandle();
	CSGXRumbleState *pState = &m_RumbleStateList[id];

	pState->m_pProfile = pProfile;
	pState->m_fStrength = fStrength;
	pState->m_fDuration= fDuration;
	pState->m_fTimecum = 0;

	pState->m_bDurationValid= TRUE;
	pState->m_bPositionValid= FALSE;

	return id;
}

tUINT32 CSGXRumbleDevice::startRumble(const CSGXRumbleProfile *pProfile, const tREAL32 fStrength) {
	tUINT32 id = getNewRumbleHandle();
	CSGXRumbleState *pState = &m_RumbleStateList[id];

	pState->m_pProfile = pProfile;
	pState->m_fStrength = fStrength;

	pState->m_bDurationValid= FALSE;
	pState->m_bPositionValid= FALSE;

	return id;
}


tUINT32 CSGXRumbleDevice::playRumble(const CSGXRumbleProfile *pProfile, const sgxVector3 &vPosition, const tREAL32 fStrength, const tREAL32 fDuration) {
	tUINT32 id = getNewRumbleHandle();
	CSGXRumbleState *pState = &m_RumbleStateList[id];

	pState->m_pProfile = pProfile;
	pState->m_fStrength = fStrength;
	pState->m_fDuration= fDuration;
	pState->m_vPosition = vPosition;
	pState->m_fTimecum = 0;

	pState->m_bDurationValid= TRUE;
	pState->m_bPositionValid= TRUE;

	return id;
}

tUINT32 CSGXRumbleDevice::startRumble(const CSGXRumbleProfile *pProfile, const sgxVector3 &vPosition, const tREAL32 fStrength) {
	tUINT32 id = getNewRumbleHandle();
	CSGXRumbleState *pState = &m_RumbleStateList[id];

	pState->m_pProfile = pProfile;
	pState->m_fStrength = fStrength;
	pState->m_vPosition = vPosition;

	pState->m_bDurationValid= FALSE;
	pState->m_bPositionValid= TRUE;

	return id;
}


tUINT32 CSGXRumbleDevice::getNewRumbleHandle() {
	tUINT32  id = MAX_RUMBLES;

	// Find an unused one
	for(tUINT32  i=0;i<MAX_RUMBLES;++i) {
		if (!m_RumbleStateList[i].isOn()) {
			id = i;
		}
	}

	// If non are unused, then grab any unimportant one
	// in this case, the first - since we're lazy :)
	if (id == MAX_RUMBLES) {
		id = 0;
	}

	// Now clear it
	m_RumbleStateList[id].m_fTimecum  = 0;

	return id;
}

