/////////////////////////////////////////////////////////////////////////////
// File:        wiimotes_types.cpp
// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
// 
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
/////////////////////////////////////////////////////////////////////////////

#include "mod_wiimotes/wiimotes_types.h"
#include <string.h>
// Visual C++ complains about the structs defined in wiiuse.h
// so we disable the meaningless warnings
#if defined(_MSC_VER)
#pragma warning (disable:4510)
#pragma warning (disable:4512)
#pragma warning (disable:4610)
#define snprintf _snprintf
#endif
#include "wiiuse/include/wiiuse.h"

using namespace spcore;

namespace mod_wiimotes {

/**
 Class to store and notify wiimotes status
*/

CTypeWiimotesStatusContents::CTypeWiimotesStatusContents(int id) 
: CTypeAny(id)
{
	Reset();	
}

void CTypeWiimotesStatusContents::Reset()
{
	m_generalStatus= IDLE;
	m_connectedCount= 0;
	for (int i= 0; i< MAXWIIMOTES; ++i) { 
		m_wiimoteStatus[i]= NONE;
		m_enabledFeatures[i]= ENABLED_NONE;
	}
}

bool CTypeWiimotesStatusContents::IsConnected(unsigned int wiimote_n) const {
	assert (wiimote_n< MAXWIIMOTES);
	if (wiimote_n>= MAXWIIMOTES) return 0;
	return ((m_wiimoteStatus[wiimote_n] & WIIMOTE_CONNECTED)== WIIMOTE_CONNECTED);
}

bool CTypeWiimotesStatusContents::HasNunchuk(unsigned int wiimote_n) const {
	assert (wiimote_n< MAXWIIMOTES);
	if (wiimote_n>= MAXWIIMOTES) return NONE;
	return (m_wiimoteStatus[wiimote_n] & NUNCHUK)!= 0;
}

bool CTypeWiimotesStatusContents::HasClassicPad(unsigned int wiimote_n) const {
	assert (wiimote_n< MAXWIIMOTES);
	if (wiimote_n>= MAXWIIMOTES) return NONE;
	return (m_wiimoteStatus[wiimote_n] & CLASSIC)!= 0;
}

bool CTypeWiimotesStatusContents::HasGuitarHero(unsigned int wiimote_n) const {
	assert (wiimote_n< MAXWIIMOTES);
	if (wiimote_n>= MAXWIIMOTES) return NONE;
	return (m_wiimoteStatus[wiimote_n] & GUITAR_HERO)!= 0;
}

bool CTypeWiimotesStatusContents::HasBalanceBoard(unsigned int wiimote_n) const {
	assert (wiimote_n< MAXWIIMOTES);
	if (wiimote_n>= MAXWIIMOTES) return NONE;
	return (m_wiimoteStatus[wiimote_n] & BALANCE_BOARD)!= 0;
}

bool CTypeWiimotesStatusContents::HasMotionPlus(unsigned int wiimote_n) const {
	assert (wiimote_n< MAXWIIMOTES);
	if (wiimote_n>= MAXWIIMOTES) return NONE;
	return (m_wiimoteStatus[wiimote_n] & MOTION_PLUS)!= 0;
}

//
// Accessors to query which features are enabled
//
bool CTypeWiimotesStatusContents::IsAccelerometersEnabled(unsigned int wiimote_n) const {
	assert (wiimote_n< MAXWIIMOTES);
	if (wiimote_n>= MAXWIIMOTES) return false;
	return (m_enabledFeatures[wiimote_n] & CTypeWiimotesStatusContents::ENABLED_ACC? true : false);
}

bool CTypeWiimotesStatusContents::IsMotionPlusEnabled(unsigned int wiimote_n) const {
	assert (wiimote_n< MAXWIIMOTES);
	if (wiimote_n>= MAXWIIMOTES) return false;
	return (m_enabledFeatures[wiimote_n] & CTypeWiimotesStatusContents::ENABLED_MP? true : false);
}

bool CTypeWiimotesStatusContents::IsNunchuckEnabled(unsigned int wiimote_n) const
{
	assert (wiimote_n< MAXWIIMOTES);
	if (wiimote_n>= MAXWIIMOTES) return false;
	return (m_enabledFeatures[wiimote_n] & CTypeWiimotesStatusContents::ENABLED_NUNCHUCK? true : false);
}

void CTypeWiimotesStatusContents::SetIsConnected(unsigned int wiimote_n, bool v) {
	unsigned int value= m_wiimoteStatus[wiimote_n];
	assert (wiimote_n< MAXWIIMOTES);
	if (v) {
		value|= WIIMOTE_CONNECTED;
		m_wiimoteStatus[wiimote_n]= static_cast<Extension>(value);
	}
	else 
		m_wiimoteStatus[wiimote_n]= NONE;	
}

void CTypeWiimotesStatusContents::SetExtension (unsigned int wiimote_n, Extension e) {
	assert (wiimote_n< MAXWIIMOTES);
	// clear lower bits, only one extensions is allowed
	unsigned int value= m_wiimoteStatus[wiimote_n] & WIIMOTE_CONNECTED;
	// store lower bytes
	value|= e;
	m_wiimoteStatus[wiimote_n]= static_cast<Extension>(value);
}

/* *****************************************************************************
	CTypeWiimotesButtonsContents
***************************************************************************** */
bool CTypeWiimotesButtonsContents::IsPressedA() const {
	return (m_wiimoteButtons & WIIMOTE_BUTTON_A? true : false);
}

bool CTypeWiimotesButtonsContents::IsPressedB() const {
	return (m_wiimoteButtons & WIIMOTE_BUTTON_B? true : false);
}

bool CTypeWiimotesButtonsContents::IsPressedOne() const {
	return (m_wiimoteButtons & WIIMOTE_BUTTON_ONE? true : false);
}

bool CTypeWiimotesButtonsContents::IsPressedTwo() const {
	return (m_wiimoteButtons & WIIMOTE_BUTTON_TWO? true : false);
}

bool CTypeWiimotesButtonsContents::IsPressedMinus() const {
	return (m_wiimoteButtons & WIIMOTE_BUTTON_MINUS? true : false);
}

bool CTypeWiimotesButtonsContents::IsPressedPlus() const {
	return (m_wiimoteButtons & WIIMOTE_BUTTON_PLUS? true : false);
}

bool CTypeWiimotesButtonsContents::IsPressedHome() const {
	return (m_wiimoteButtons & WIIMOTE_BUTTON_HOME? true : false);
}

bool CTypeWiimotesButtonsContents::IsPressedUp() const {
	return (m_wiimoteButtons & WIIMOTE_BUTTON_UP? true : false);
}

bool CTypeWiimotesButtonsContents::IsPressedDown() const {
	return (m_wiimoteButtons & WIIMOTE_BUTTON_DOWN? true : false);
}

bool CTypeWiimotesButtonsContents::IsPressedLeft() const {
	return (m_wiimoteButtons & WIIMOTE_BUTTON_LEFT? true : false);
}

bool CTypeWiimotesButtonsContents::IsPressedRight() const {
	return (m_wiimoteButtons & WIIMOTE_BUTTON_RIGHT? true : false);
}

// nunchuck
bool CTypeWiimotesButtonsContents::IsPressedC() const {
	return (m_nunchuckButtons & NUNCHUK_BUTTON_C? true : false);
}

bool CTypeWiimotesButtonsContents::IsPressedZ() const {
	return (m_nunchuckButtons & NUNCHUK_BUTTON_Z? true : false);
}

bool CTypeWiimotesButtonsContents::IsPressedAny() const {
	return (m_wiimoteButtons | m_nunchuckButtons? true : false);
}

};