/* 
 * Copyright (c) 2006, Ben Supnik.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a 
 * copy of this software and associated documentation files (the "Software"), 
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 
 * and/or sell copies of the Software, and to permit persons to whom the 
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
 * THE SOFTWARE.
 *
 */
#include "XPLMProcessing.h"
#include "XPLMDataAccess.h"
#include "XPLMUtilities.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#include "unimotion.h"
#include <algorithm>
using std::min;
using std::max;

int					gSMS = unknown;

PLUGIN_API int XPluginStart(
						char *		outName,
						char *		outSig,
						char *		outDesc)
{
	strcpy(outName, "SMSHack");
	strcpy(outSig, "xpsdk.examples.sms_hack");
	strcpy(outDesc, "A plugin that uses a MacBook's gyros to fly.");		

	return 1;
}

PLUGIN_API void	XPluginStop(void)
{
}

inline float calibrate (int now, int minv, int maxv)
{
	if (minv == maxv) return 0.0;
	float dist = maxv - minv;
	float base = now - minv;
	float rat = base / dist;
	return rat * 2.0 - 1.0;
}


float		sms_callback(float elapsedMe, float elapsedSim, int counter, void * refcon)
{
	if (gSMS != unknown)
	{
		static XPLMDataRef pitch_ref = XPLMFindDataRef("sim/joystick/yolk_pitch_ratio");
		static XPLMDataRef heading_ref = XPLMFindDataRef("sim/joystick/yolk_heading_ratio");
		static XPLMDataRef roll_ref = XPLMFindDataRef("sim/joystick/yolk_roll_ratio");
		
		static int pitch_min = 0, pitch_max = 0, roll_min = 0, roll_max = 0, heading_min = 0, heading_max = 0;
		int pitch, roll, heading;
		if (read_sms_raw(gSMS, &roll, &pitch, &heading))
		{
			pitch_min = min(pitch_min, pitch);
			pitch_max = max(pitch_max, pitch);
			heading_min = min(heading_min, heading);
			heading_max = max(heading_max, heading);
			roll_min = min(roll_min, roll);
			roll_max = max(roll_max, roll);
			
			XPLMSetDataf(pitch_ref, calibrate(pitch, pitch_min, pitch_max));
//			Ben says: because yaw axis of the powerbook only notices displacement (since gravity
//			is ALWAYS in the plane of rotation) you basically can't calibrate yaw so
//			I will not use it.
//			XPLMSetDataf(heading_ref, calibrate(heading, heading_min, heading_max));
			XPLMSetDataf(roll_ref, -calibrate(roll, roll_min, roll_max));			
		}
	}
	return -1;
}


PLUGIN_API void XPluginDisable(void)
{
	XPLMSetDatai(XPLMFindDataRef("sim/operation/override/override_joystick"),0);
	XPLMUnregisterFlightLoopCallback(sms_callback, NULL);
}

PLUGIN_API int XPluginEnable(void)
{
	gSMS = detect_sms();
	char buf[100];
	sprintf(buf,"Found SMS hardware type: %d\n",gSMS);
	XPLMDebugString(buf);
	if (gSMS != unknown)
	{
		XPLMSetDatai(XPLMFindDataRef("sim/operation/override/override_joystick"),1);
		XPLMRegisterFlightLoopCallback(sms_callback, -1.0, NULL);
	}
	return 1;
}

PLUGIN_API void XPluginReceiveMessage(XPLMPluginID inFrom, long inMsg, void * inParam)
{
}



