Hud* HudsManager::createHud(HudAlignment hudAlignment) {
	Hud *hud = new Hud();
	unsigned long hudPosition;
	
	hud->initializeHudText();
	
	if (hudAlignment == HudAlignment::LEFT) {
		this->leftHuds.push_back(hud);
		hud->setPosition(osg::Vec3(10, this->initial_Y_Position, 0));
	} else {
		this->rightHuds.push_back(hud);
		hud->setPosition(osg::Vec3(900, this->initial_Y_Position, 0));
	}
	
	hud->setText("");
	osg::Camera *hudCamera = hud->getHudCamera();
	game->getRoot()->addChild(hudCamera);
	
	
	// update huds positions
	hudPosition = this->leftHuds.size();
	for (Hud* h : this->leftHuds)
		h->setPosition(osg::Vec3(h->getPosition().x(), ((hudPosition--) * 25) + this->initial_Y_Position + 10, 0));

	hudPosition = this->rightHuds.size();
	for (Hud* h : this->rightHuds)
		h->setPosition(osg::Vec3(h->getPosition().x(), ((hudPosition--) * 25) + this->initial_Y_Position + 10, 0));
	
	return hud;
}
void RealTimeTest::maxSpead() {
    
	Hud *maxSpeadTestingHud = game.getHudsManager()->createHud(HudAlignment::RIGHT);
	maxSpeadTestingHud->setText("MAX SPEAD TESTING STARTED...");
	
	DelayCommand dc(15);
	dc.execute();
	
	Helicopter *helicopter = game.getHelicopter();
	JoystickMoveForward jmf(helicopter->getJoystick());
	RotorNeutral rn(helicopter->getMainRotor());
	float oldV = 0;
	float newV = 0;
	
	std::cout << "\nmaxSpead test started:" << std::endl;
	
	game.getConfiguration()->activateFriction();
	helicopter->reset();
	helicopter->setPosistion(osg::Vec3f(0, 0, 600));
	jmf.execute();
	rn.execute();
	
	
	do {
		oldV = newV;
		dc.execute();
		newV = helicopter->getVelocity().x();
	} while (oldV < newV);
	
	
	// viscous resistance = v * (6 * WORLD_PI * 0.001 * 4)
	// if joystick(theta = 15, phi = 0) and throttle(9.8), then
	// ax = sin15 * 9.8 = 0.2588 * 9.8 = 2.53624
	// viscous resistance should be equal 2.53624
	// v * (6 * WORLD_PI * 0.001 * 4) = 2.53624 <= now solve for v
	// v = 2.53624 / (6 * WORLD_PI * 0.001 * 4)
	// v = 33.6379
	Assert(33.6379, helicopter->getVelocity().x(), 0.01);
	
	std::cout << "maxSpead test passed" << std::endl;
	std::cout << "maxSpead test results:" << std::endl;
	std::cout << "vx = " << helicopter->getVelocity().x() << std::endl;
    maxSpeadTestingHud->setText("HOVER TESTING PASSED...");
}
void RealTimeTest::hover() {
	
	Hud *hoverTestingHud = game.getHudsManager()->createHud(HudAlignment::RIGHT);
	hoverTestingHud->setText("HOVER TESTING STARTED...");
	
	DelayCommand dc(2);
	DelayCommand wait10s(10);
	dc.execute();
	
	std::cout << "\nhover test started:" << std::endl;
	
	game.getConfiguration()->deactivateFriction();
	Helicopter *helicopter = game.getHelicopter();
	
	helicopter->reset();
	helicopter->setPosistion(osg::Vec3f(0, 0, 0));
	helicopter->getMainRotor()->increaseMagnitude();
	helicopter->getMainRotor()->increaseMagnitude();
	helicopter->getMainRotor()->increaseMagnitude();
	
	wait10s.execute();
	
	
	// after 10s should be at position 15m
	// a = 0.3
	// x = 0 + 0*10 + 0.5 * 0.3 * (10)^2 = 15
	// v = 0 + a * t
	// v = 0.3 * 10 = 3
    
	Assert(15.0, helicopter->getPosistion().z(), 1.0e-1);
	Assert(3.0, helicopter->getVelocity().z(), 1.0e-1);
	Assert(0.3, helicopter->getAcceleration().z(), 1.0e-1);
	
	std::cout << "hover test passed" << std::endl;
	std::cout << "hover test results:" << std::endl;
	std::cout << "pz = " << helicopter->getPosistion().z() << std::endl;
	std::cout << "vz = " << helicopter->getVelocity().z() << std::endl;
	std::cout << "az = " << helicopter->getAcceleration().z() << std::endl;
    
	hoverTestingHud->setText("HOVER TESTING PASSED...");
}
void RealTimeTest::run() {

	game.initialize();
	game.getPopupHelpScreen()->hide();
	Hud *testingHud = game.getHudsManager()->createHud(HudAlignment::RIGHT);
	testingHud->setText("TESTING...");
	
	std::thread startHoverTest(RealTimeTest::hover);
	std::thread startMaxSpeadTest(RealTimeTest::maxSpead);
	
	game.run();
	
	startHoverTest.join();
	startMaxSpeadTest.join();
	
	delete testingHud;
}
void Game::initializePopupHelpScreen() {
	
	if (popupHelpScreen)
		delete popupHelpScreen;
		
	this->popupHelpScreen = new HudsManager(this, this->configuration->getScreenHeight() / 2);
	
	Hud *titleHud = popupHelpScreen->createHud(HudAlignment::LEFT);
	Hud *mouseHud;
	Hud *movementHud;
	
	if (this->configuration->isMouseControl())
		mouseHud = popupHelpScreen->createHud(HudAlignment::LEFT);
	else
		movementHud = popupHelpScreen->createHud(HudAlignment::LEFT);
	
	Hud *resetJoystickHud = popupHelpScreen->createHud(HudAlignment::LEFT);
	Hud *zeroRotorSpeedHud = popupHelpScreen->createHud(HudAlignment::LEFT);
	Hud *increase_decreaseRotorSpeedHud = popupHelpScreen->createHud(HudAlignment::LEFT);
	Hud *neutralRotorModeHud = popupHelpScreen->createHud(HudAlignment::LEFT);
	Hud *rotationHud = popupHelpScreen->createHud(HudAlignment::LEFT);
	Hud *fireHud = popupHelpScreen->createHud(HudAlignment::LEFT);
	Hud *increment_decrementInclinationAngleHud = popupHelpScreen->createHud(HudAlignment::LEFT);
	Hud *increment_decrementMissileInitialSpeedHud = popupHelpScreen->createHud(HudAlignment::LEFT);
	Hud *frictionEnable_DisableHud = popupHelpScreen->createHud(HudAlignment::LEFT);
	Hud *startLoggingHud = popupHelpScreen->createHud(HudAlignment::LEFT);
	Hud *stopLoggingHud = popupHelpScreen->createHud(HudAlignment::LEFT);
	Hud *updateHud = popupHelpScreen->createHud(HudAlignment::LEFT);
	Hud *showHelpHud = popupHelpScreen->createHud(HudAlignment::LEFT);
	Hud *hideHelpHud = popupHelpScreen->createHud(HudAlignment::LEFT);
	
	titleHud->setText("Settings");
	
	if (this->configuration->isMouseControl())
		mouseHud->setText("Mouse contorl the joystick");
	else {
		movementHud->setText(
							 std::string(1, this->configuration->getKeySettings().movingForward) + ", " +
							 std::string(1, this->configuration->getKeySettings().movingRight) + ", " +
							 std::string(1, this->configuration->getKeySettings().movingLeft) + ", " +
							 std::string(1, this->configuration->getKeySettings().movingBackward) +
							 ": moving forward, left, right, backward"
							 );
	}
		
	
	resetJoystickHud->setText(
			std::string(1, this->configuration->getKeySettings().resetJoystick) + ": reset joystick");
	
	zeroRotorSpeedHud->setText(
			std::string(1, this->configuration->getKeySettings().zeroRotorSpeed) + ": zero rotor speed");
	
	increase_decreaseRotorSpeedHud->setText(
			std::string(1, this->configuration->getKeySettings().increaseRotorSpeed) + "/" +
			std::string(1, this->configuration->getKeySettings().decreaseRotorSpeed) + ": +/- rotor speed");
	
	neutralRotorModeHud->setText(
			std::string(1, this->configuration->getKeySettings().neutralRotorMode) + ": neutral rotor mode");
	
	rotationHud->setText(
			std::string(1, this->configuration->getKeySettings().rotateLeft) + "/" +
			std::string(1, this->configuration->getKeySettings().rotateRight) + ": rotate left/right");
	
	fireHud->setText(
			std::string(1, this->configuration->getKeySettings().fire) + ": fire");
	
	increment_decrementInclinationAngleHud->setText(
			std::string(1, this->configuration->getKeySettings().incrementInclinationAngle) + "/" +
			std::string(1, this->configuration->getKeySettings().decrementInclinationAngle) +
													": +/- inclination angle");
	
	increment_decrementMissileInitialSpeedHud->setText(
			std::string(1, this->configuration->getKeySettings().incrementMissileInitialSpeed) + "/" +
			std::string(1, this->configuration->getKeySettings().decrementMissileInitialSpeed) +
													   + ": +/- increment missile initial speed");
	
	frictionEnable_DisableHud->setText(
			std::string(1, this->configuration->getKeySettings().frictionEnable) + "/" +
			std::string(1, this->configuration->getKeySettings().frictionDisable) +
									   + ": enable/disable friction");
	
	startLoggingHud->setText(
					   std::string(1, this->configuration->getKeySettings().startLogging) + ": start logging");
	
	stopLoggingHud->setText(
					   std::string(1, this->configuration->getKeySettings().stopLogging) + ": stop logging");
	
	updateHud->setText(
			std::string(1, this->configuration->getKeySettings().updateKeySettings) + ": updste key settings");
	
	showHelpHud->setText(
			std::string(1, this->configuration->getKeySettings().showPopupHelpScreen) + ": show help screen");
	
	hideHelpHud->setText(
			std::string(1, this->configuration->getKeySettings().hidePopupHelpScreen) + ": hide help screen");
}