////////////////////////////////////////////////////////////////////////////////
// PlayerGroundVehicle.cpp
// Class that controls a player's biped mech
// Copyright Bjoern Ganster
// Developed since 2010
////////////////////////////////////////////////////////////////////////////////

#include "PlayerGroundVehicle.h"
#include "MechSim.h"
#include "VehicleAI.h"

#include <iostream>

#define FILE_NUMBER FILE_NO_PLAYER_BIPED_MECH_CPP

// Constructor
PlayerGroundVehicle::PlayerGroundVehicle(Vehicle* mech)
: PlayerVehicleAI("PlayerGroundVehicle", PlayerVehicleAIID, mech),
  mBraking(false)
{
}

// Destructor
PlayerGroundVehicle::~PlayerGroundVehicle() 
{
}

// Check if a weapon is currently active - used by the HUD
bool PlayerGroundVehicle::weaponActive(int i, bool groupFire) const
{
	if (mVehicle != nullptr) {
		if (groupFire) {
			int group = mVehicle->getGroup(i);
			return (group == mVehicle->mActiveWeapon);
		} else {
			return (i == mVehicle->mActiveWeapon);
		}
	} else {
		return false;
	}
}

void PlayerGroundVehicle::setTarget(GameObject* gameObject)
{
	mTarget = gameObject;
}

// Notify AI of an event, like a destroyed object
void PlayerGroundVehicle::updateObjectStatus(const BGCPString& id, SubObjectiveType newStatus) 
{
}

void PlayerGroundVehicle::setThrottleOrWeaponGroup(BGKey key, bool shiftHeld)
{
	if (mVehicle != nullptr) {
		if (shiftHeld) {
			mVehicle->setActiveWeaponGroup(key-'1');
		} /*else {
			if (key='0') {
				setThrottle(1.0);
			} else {
				setThrottle((key-'1') / 9.0);
			}
		}*/
	}
}

// Keyboard event handler
void PlayerGroundVehicle::keypressed(BGKey key, bool shiftHeld, bool controlHeld, bool down, bool repeat)
{
	Point3D front = mVehicle->p_front;
	Point3D left = mVehicle->p_left;
	MechSim* sim = getMechSim();
	auto environment = sim->getEnvironment();
	double maxTurnPerSecond = mVehicle->getMaxTurnPerSecond();

	switch (key) {
		case SDLK_RETURN:
			if (mVehicle != nullptr && down && !repeat) {
				mVehicle->nextWeapon();
			}
			break;
		case '1':
		case '2':
		case '3':
		case '4':
		case '5':
		case '6':
		case '7':
		case '8':
		case '9':
		case '0':
			if (down && !repeat) {
				setThrottleOrWeaponGroup(key, shiftHeld);
			}
			break;
		case 'c':
			if (down && !repeat) {
				sim->setFreeViewTheta(0.0);
				mPerspective = (mPerspective + 1) % 2;
			}
			break;
		case 'i':
				if (mTarget != nullptr) {
					Point3D ownPos = mVehicle->getPosition();
					// getPosition yields local coordinates, but we need coordinates in the top-hierarchy of coordinate systems
					//Point3D targetPos = target->getPosition();
					Point3D min, max;
					mTarget->getMinCoords(min);
					mTarget->getMaxCoords(max);
					Point3D targetPos = 0.5 * (min+max);
					double dist = (ownPos-targetPos).length();
					if (dist < 200) {
						mTarget->setInspected(true);
						sim->updateObjectStatus(mTarget->getID(), SubObjectiveType::inspect, false);
					}
				}
				break;
		case 'n':
			if (!shiftHeld && down) {
				if (mTarget != nullptr) {
					mTarget = nullptr;
				} else {
					sim->selectNextNavPoint();
				}
			}
			break;
		case 'j':
			if (environment != underwater) {
				if (down && mVehicle->mJumpJetFuel > 0) {
					mVehicle->mAcceleration.y = jjStrength;
					mVehicle->mJumpJetsActive.y = 1;
					#ifdef MECHVM
					sim->playSound("MECJJRXX.sfl");
					#endif
				} else {
					mVehicle->mAcceleration.y = 0.0;
					mVehicle->mJumpJetsActive.y = 0;
				}
			}
			break;
		case 'q':
			mTarget = sim->findTarget();
			break;
		case 'x':
			if (!shiftHeld && down) {
				sim->adjustSatelliteDist(0.5);
			}
			if (shiftHeld && down) {
				sim->adjustSatelliteDist(2.0);
			}
			break;
		case '#':
			if (down && !repeat) {
				groupFire = !groupFire;
			}
			break;
		case SDLK_HOME:
			if (environment != underwater) {
				if (down && mVehicle->mJumpJetFuel > 0) {
					mVehicle->mAcceleration.x = mVehicle->p_front.x * jjStrength;
					mVehicle->mAcceleration.z = mVehicle->p_front.z * jjStrength;
					mVehicle->mJumpJetsActive.z = 1;
				} else {
					mVehicle->mAcceleration.x = 0.0;
					mVehicle->mAcceleration.z = 0.0;
					mVehicle->mJumpJetsActive.x = 0;
				}
			}
			break;
		case SDLK_DELETE:
			if (environment != underwater) {
				if (down && mVehicle->mJumpJetFuel > 0) {
					mVehicle->mAcceleration.x = -mVehicle->p_left.x * jjStrength;
					mVehicle->mAcceleration.z = -mVehicle->p_left.z * jjStrength;
					mVehicle->mJumpJetsActive.x = -1;
				} else {
					mVehicle->mAcceleration.x = 0.0;
					mVehicle->mAcceleration.z = 0.0;
					mVehicle->mJumpJetsActive.x = 0;
				}
			}
			break;
		case SDLK_END:
			if (environment != underwater) {
				if (down && mVehicle->mJumpJetFuel > 0) {
					mVehicle->mAcceleration.x = -mVehicle->p_front.x * jjStrength;
					mVehicle->mAcceleration.z = -mVehicle->p_front.z * jjStrength;
					mVehicle->mJumpJetsActive.z = 1;
				} else {
					mVehicle->mAcceleration.x = 0.0;
					mVehicle->mAcceleration.z = 0.0;
					mVehicle->mJumpJetsActive.z = 0;
				}
			}
			break;
		case SDLK_PAGEDOWN:
			if (environment != underwater) {
				if (down && mVehicle->mJumpJetFuel > 0) {
					mVehicle->mAcceleration.x = mVehicle->p_left.x * jjStrength;
					mVehicle->mAcceleration.z = mVehicle->p_left.z * jjStrength;
					mVehicle->mJumpJetsActive.x = 1;
				} else {
					mVehicle->mAcceleration.x = 0.0;
					mVehicle->mAcceleration.z = 0.0;
					mVehicle->mJumpJetsActive.x = 0;
				}
			}
			break;
		case SDLK_LEFT:
			if (controlHeld) {
				if (down) {
					sim->setFreeViewDeltaTheta(-120);
				} else {
					sim->setFreeViewDeltaTheta(0);
				}
			} else {
				mVehicle->m_turnDelta = down ? -maxTurnPerSecond : 0.0;
			}
			break;
		case SDLK_UP:
			if (down)
				mVehicle->m_speedDelta = 1.0;
			else
				mVehicle->m_speedDelta = 0.0;
			break;
		case SDLK_RIGHT:
			if (controlHeld) {
				if (down) {
					sim->setFreeViewDeltaTheta(120);
				} else {
					sim->setFreeViewDeltaTheta(0);
				}
			} else {
			mVehicle->m_turnDelta = down ? maxTurnPerSecond : 0.0;
			}
			break;
		case SDLK_DOWN:
			if (down)
				mVehicle->m_speedDelta = -1.0;
			else
				mVehicle->m_speedDelta = 0.0;
			break;
		case SDLK_BACKSPACE:
			if (down) {
				mBraking = true;
			} else {
				mBraking = false;
				mVehicle->m_speedDelta = 0.0;
			}
			break;
	}

	mVehicle->p_left = left;
	mVehicle->p_front = front;
}

void PlayerGroundVehicle::planMovement(DWORD now)
{
	if (mBraking) {
		double vehicleSpeed = mVehicle->getSpeed();
		if (vehicleSpeed > 0.01) {
			if (vehicleSpeed > 1.0) {
				mVehicle->m_speedDelta = -1.0;
			} else {
				mVehicle->m_speedDelta = -vehicleSpeed / 4;
			}
		} else if (vehicleSpeed < -0.01) {
			if (vehicleSpeed < -1.0) {
				mVehicle->m_speedDelta = 1.0;
			} else {
				mVehicle->m_speedDelta = -vehicleSpeed / 4;
			}
		}
	}
}

// Button state changed over a window: returns child that was clicked
void PlayerGroundVehicle::buttonStateChanged(int button, bool down, int /*x*/, int /*y*/)
{
	const MechSim* mechSim = getMechSim();
	DWORD now = mechSim->missionTime();
	if (mVehicle != nullptr && down) {
		if (button == SDL_BUTTON_LEFT) {
			if (mVehicle->canFireWeapon(mVehicle->mActiveWeapon, now) || groupFire)
			{
				mVehicle->fireWeapons(groupFire, now);
			} else {
				mVehicle->cycleWeapon(groupFire);
			}
		} else {
			mVehicle->cycleWeapon(groupFire);
		}
	}
}

// Notify AI of mouse movement event
void PlayerGroundVehicle::mouseMoved(int /*x*/, int /*y*/)
{
}

void PlayerGroundVehicle::setAim(double dx, double dy)
{
	mVehicle->setAim(90.0 - 180.0 * dx, 60 * dy - 30);
}
