/*
 * Copyright 2010-2016 OpenXcom Developers.
 *
 * This file is part of OpenXcom.
 *
 * OpenXcom 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.
 *
 * OpenXcom 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 OpenXcom.  If not, see <http://www.gnu.org/licenses/>.
 */
#include "SelectDestinationState.h"
#include <cmath>
#include "../Engine/Game.h"
#include "../Engine/Screen.h"
#include "../Engine/Action.h"
#include "../Mod/Mod.h"
#include "../Engine/LocalizedText.h"
#include "../Engine/Surface.h"
#include "../Interface/Window.h"
#include "Globe.h"
#include "../Interface/Text.h"
#include "../Interface/TextButton.h"
#include "../Savegame/Waypoint.h"
#include "MultipleTargetsState.h"
#include "../Savegame/SavedGame.h"
#include "../Savegame/Craft.h"
#include "../Mod/RuleCraft.h"
#include "ConfirmCydoniaState.h"
#include "../Engine/Options.h"
 
namespace OpenXcom
{
 
/**
 * Initializes all the elements in the Select Destination window.
 * @param game Pointer to the core game.
 * @param craft Pointer to the craft to target.
 * @param globe Pointer to the Geoscape globe.
 */
SelectDestinationState::SelectDestinationState(Craft *craft, Globe *globe) : _craft(craft), _globe(globe)
{
	int dx = _game->getScreen()->getDX();
	int dy = _game->getScreen()->getDY();
	_screen = false;
 
	// Create objects
	_btnRotateLeft = new InteractiveSurface(12, 10, 259 + dx * 2, 176 + dy);
	_btnRotateRight = new InteractiveSurface(12, 10, 283 + dx * 2, 176 + dy);
	_btnRotateUp = new InteractiveSurface(13, 12, 271 + dx * 2, 162 + dy);
	_btnRotateDown = new InteractiveSurface(13, 12, 271 + dx * 2, 187 + dy);
	_btnZoomIn = new InteractiveSurface(23, 23, 295 + dx * 2, 156 + dy);
	_btnZoomOut = new InteractiveSurface(13, 17, 300 + dx * 2, 182 + dy);
 
	_window = new Window(this, 256, 28, 0, 0);
	_window->setX(dx);
	_window->setDY(0);
	_btnCancel = new TextButton(60, 12, 110 + dx, 8);
	_btnCydonia = new TextButton(60, 12, 180 + dx, 8);
	_txtTitle = new Text(100, 16, 10 + dx, 6);
 
	// Set palette
	setInterface("geoscape");
 
	add(_btnRotateLeft);
	add(_btnRotateRight);
	add(_btnRotateUp);
	add(_btnRotateDown);
	add(_btnZoomIn);
	add(_btnZoomOut);
 
	add(_window, "genericWindow", "geoscape");
	add(_btnCancel, "genericButton1", "geoscape");
	add(_btnCydonia, "genericButton1", "geoscape");
	add(_txtTitle, "genericText", "geoscape");
 
	// Set up objects
	_globe->onMouseClick((ActionHandler)&SelectDestinationState::globeClick);
 
	_btnRotateLeft->onMousePress((ActionHandler)&SelectDestinationState::btnRotateLeftPress);
	_btnRotateLeft->onMouseRelease((ActionHandler)&SelectDestinationState::btnRotateLeftRelease);
	_btnRotateLeft->onKeyboardPress((ActionHandler)&SelectDestinationState::btnRotateLeftPress, Options::keyGeoLeft);
	_btnRotateLeft->onKeyboardRelease((ActionHandler)&SelectDestinationState::btnRotateLeftRelease, Options::keyGeoLeft);
 
	_btnRotateRight->onMousePress((ActionHandler)&SelectDestinationState::btnRotateRightPress);
	_btnRotateRight->onMouseRelease((ActionHandler)&SelectDestinationState::btnRotateRightRelease);
	_btnRotateRight->onKeyboardPress((ActionHandler)&SelectDestinationState::btnRotateRightPress, Options::keyGeoRight);
	_btnRotateRight->onKeyboardRelease((ActionHandler)&SelectDestinationState::btnRotateRightRelease, Options::keyGeoRight);
 
	_btnRotateUp->onMousePress((ActionHandler)&SelectDestinationState::btnRotateUpPress);
	_btnRotateUp->onMouseRelease((ActionHandler)&SelectDestinationState::btnRotateUpRelease);
	_btnRotateUp->onKeyboardPress((ActionHandler)&SelectDestinationState::btnRotateUpPress, Options::keyGeoUp);
	_btnRotateUp->onKeyboardRelease((ActionHandler)&SelectDestinationState::btnRotateUpRelease, Options::keyGeoUp);
 
	_btnRotateDown->onMousePress((ActionHandler)&SelectDestinationState::btnRotateDownPress);
	_btnRotateDown->onMouseRelease((ActionHandler)&SelectDestinationState::btnRotateDownRelease);
	_btnRotateDown->onKeyboardPress((ActionHandler)&SelectDestinationState::btnRotateDownPress, Options::keyGeoDown);
	_btnRotateDown->onKeyboardRelease((ActionHandler)&SelectDestinationState::btnRotateDownRelease, Options::keyGeoDown);
 
	_btnZoomIn->onMouseClick((ActionHandler)&SelectDestinationState::btnZoomInLeftClick, SDL_BUTTON_LEFT);
	_btnZoomIn->onMouseClick((ActionHandler)&SelectDestinationState::btnZoomInRightClick, SDL_BUTTON_RIGHT);
	_btnZoomIn->onKeyboardPress((ActionHandler)&SelectDestinationState::btnZoomInLeftClick, Options::keyGeoZoomIn);
 
	_btnZoomOut->onMouseClick((ActionHandler)&SelectDestinationState::btnZoomOutLeftClick, SDL_BUTTON_LEFT);
	_btnZoomOut->onMouseClick((ActionHandler)&SelectDestinationState::btnZoomOutRightClick, SDL_BUTTON_RIGHT);
	_btnZoomOut->onKeyboardPress((ActionHandler)&SelectDestinationState::btnZoomOutLeftClick, Options::keyGeoZoomOut);
 
	// dirty hacks to get the rotate buttons to work in "classic" style
	_btnRotateLeft->setListButton();
	_btnRotateRight->setListButton();
	_btnRotateUp->setListButton();
	_btnRotateDown->setListButton();
 
	_window->setBackground(_game->getMod()->getSurface("BACK01.SCR"));
 
	_btnCancel->setText(tr("STR_CANCEL_UC"));
	_btnCancel->onMouseClick((ActionHandler)&SelectDestinationState::btnCancelClick);
	_btnCancel->onKeyboardPress((ActionHandler)&SelectDestinationState::btnCancelClick, Options::keyCancel);
 
	_txtTitle->setText(tr("STR_SELECT_DESTINATION"));
	_txtTitle->setVerticalAlign(ALIGN_MIDDLE);
	_txtTitle->setWordWrap(true);
 
	if (!_craft->getRules()->getSpacecraft() || !_game->getSavedGame()->isResearched(_game->getMod()->getFinalResearch()))
	{
		_btnCydonia->setVisible(false);
	}
	else
	{
		_btnCydonia->setText(tr("STR_CYDONIA"));
		_btnCydonia->onMouseClick((ActionHandler)&SelectDestinationState::btnCydoniaClick);
	}
 
	if (_craft->getStatus() != "STR_OUT")
	{
		_globe->setCraftRange(_craft->getLongitude(), _craft->getLatitude(), _craft->getBaseRange());
		_globe->invalidate();
	}
}
 
/**
 *
 */
SelectDestinationState::~SelectDestinationState()
{
	_globe->setCraftRange(0.0, 0.0, 0.0);
}
 
/**
 * Stop the globe movement.
 */
void SelectDestinationState::init()
{
	State::init();
	_globe->rotateStop();
}
 
/**
 * Runs the globe rotation timer.
 */
void SelectDestinationState::think()
{
	State::think();
	_globe->think();
}
 
/**
 * Handles the globe.
 * @param action Pointer to an action.
 */
void SelectDestinationState::handle(Action *action)
{
	State::handle(action);
	_globe->handle(action, this);
}
 
/**
 * Processes any left-clicks for picking a target,
 * or right-clicks to scroll the globe.
 * @param action Pointer to an action.
 */
void SelectDestinationState::globeClick(Action *action)
{
	double lon, lat;
	int mouseX = (int)floor(action->getAbsoluteXMouse()), mouseY = (int)floor(action->getAbsoluteYMouse());
	_globe->cartToPolar(mouseX, mouseY, &lon, &lat);
 
	// Ignore window clicks
	if (mouseY < 28)
	{
		return;
	}
 
	// Clicking on a valid target
	if (action->getDetails()->button.button == SDL_BUTTON_LEFT)
	{
		std::vector<Target*> v = _globe->getTargets(mouseX, mouseY, true);
		if (v.empty())
		{
			Waypoint *w = new Waypoint();
			w->setLongitude(lon);
			w->setLatitude(lat);
			v.push_back(w);
		}
		_game->pushState(new MultipleTargetsState(v, _craft, 0));
	}
}
 
/**
 * Starts rotating the globe to the left.
 * @param action Pointer to an action.
 */
void SelectDestinationState::btnRotateLeftPress(Action *)
{
	_globe->rotateLeft();
}
 
/**
 * Stops rotating the globe to the left.
 * @param action Pointer to an action.
 */
void SelectDestinationState::btnRotateLeftRelease(Action *)
{
	_globe->rotateStopLon();
}
 
/**
 * Starts rotating the globe to the right.
 * @param action Pointer to an action.
 */
void SelectDestinationState::btnRotateRightPress(Action *)
{
	_globe->rotateRight();
}
 
/**
 * Stops rotating the globe to the right.
 * @param action Pointer to an action.
 */
void SelectDestinationState::btnRotateRightRelease(Action *)
{
	_globe->rotateStopLon();
}
 
/**
 * Starts rotating the globe upwards.
 * @param action Pointer to an action.
 */
void SelectDestinationState::btnRotateUpPress(Action *)
{
	_globe->rotateUp();
}
 
/**
 * Stops rotating the globe upwards.
 * @param action Pointer to an action.
 */
void SelectDestinationState::btnRotateUpRelease(Action *)
{
	_globe->rotateStopLat();
}
 
/**
 * Starts rotating the globe downwards.
 * @param action Pointer to an action.
 */
void SelectDestinationState::btnRotateDownPress(Action *)
{
	_globe->rotateDown();
}
 
/**
 * Stops rotating the globe downwards.
 * @param action Pointer to an action.
 */
void SelectDestinationState::btnRotateDownRelease(Action *)
{
	_globe->rotateStopLat();
}
 
/**
 * Zooms into the globe.
 * @param action Pointer to an action.
 */
void SelectDestinationState::btnZoomInLeftClick(Action *)
{
	_globe->zoomIn();
}
 
/**
 * Zooms the globe maximum.
 * @param action Pointer to an action.
 */
void SelectDestinationState::btnZoomInRightClick(Action *)
{
	_globe->zoomMax();
}
 
/**
 * Zooms out of the globe.
 * @param action Pointer to an action.
 */
void SelectDestinationState::btnZoomOutLeftClick(Action *)
{
	_globe->zoomOut();
}
 
/**
 * Zooms the globe minimum.
 * @param action Pointer to an action.
 */
void SelectDestinationState::btnZoomOutRightClick(Action *)
{
	_globe->zoomMin();
}
 
/**
 * Returns to the previous screen.
 * @param action Pointer to an action.
 */
void SelectDestinationState::btnCancelClick(Action *)
{
	_game->popState();
}
 
void SelectDestinationState::btnCydoniaClick(Action *)
{
	if (_craft->getNumSoldiers() > 0 || _craft->getNumVehicles() > 0)
	{
		_game->pushState(new ConfirmCydoniaState(_craft));
	}
}
 
/**
 * Updates the scale.
 * @param dX delta of X;
 * @param dY delta of Y;
 */
void SelectDestinationState::resize(int &dX, int &dY)
{
	for (std::vector<Surface*>::const_iterator i = _surfaces.begin(); i != _surfaces.end(); ++i)
	{
		(*i)->setX((*i)->getX() + dX / 2);
		if (*i != _window && *i != _btnCancel && *i != _txtTitle && *i != _btnCydonia)
		{
			(*i)->setY((*i)->getY() + dY / 2);
		}
	}
}
 
}

V524 It is odd that the body of 'btnRotateRightRelease' function is fully equivalent to the body of 'btnRotateLeftRelease' function.

V524 It is odd that the body of 'btnRotateDownRelease' function is fully equivalent to the body of 'btnRotateUpRelease' function.

V669 The 'dX', 'dY' arguments are non-constant references. The analyzer is unable to determine the position at which this argument is being modified. It is possible that the function contains an error.