#ifndef NAVIGATIONWIDGET_H
#define NAVIGATIONWIDGET_H

#include <QWidget>
#include <QLineEdit>
#include <QPushButton>
#include <QTableWidget>
#include <QLabel>
#include <map>

#include "softProj\DetailsWidget\SimpleItem.h"
#include "protocol.h"
#include "softProj\clientServer\structs.h"
#include "LocationTable.h"
#include "softProj\Main\INotifyUpdate.h"
#include "ui_navigationWidget.h"
#include "navigationDialog.h"
#include <map>

class CommandClient;

namespace Ui {
    class NavigationWidget;
}

enum EShipMovementState {
	SHIP_MOVEMENT_STATE_REGULAR,
	SHIP_MOVEMENT_STATE_STOPPED,
	SHIP_MOVEMENT_STATE_WARP,
	SHIP_MOVEMENT_STATE_ORBITING,
};

/// Widget used for ship navigation.
/**
  * Main widget encapsulating navigation widget
  *
  */
class NavigationWidget : public NotifyWidget
{
    Q_OBJECT

public:
    explicit NavigationWidget(QWidget * parent);
    ~NavigationWidget();

	void notifyUpdate() {};

    void setContextShip(const SimpleItem & item); /**< Set ship, which we want navigate. */ 

    void setPlanets(const NavigationPlanetsInStarAreaDetails & details);	/**< Sets and display list of planet. */
	void setSystems(std::vector<NavigationObject> & items); /**< Sets and display solar systems. */
	void setOwnedFortresses(std::vector<NavigationObject> & ships, std::vector<NavigationBaseObject> & bases); /**< Sets and display list of owned ships and baselines. */
	void setEnemyShips(std::vector<NavigationHighResolutionDetails> & items);	/**< Sets and display list of near enemy ships. */
	void setDistantEnemyShip(std::vector<NavigationLongRangeDetails> & items);	/**< Sets and display list of far enemy ships. */

    void systemClicked(GameItemRow * planetItem); /**< Selects solar system from list of available solar systems. */ //TODO, FIXME, COMMENTME ...diference between this and systemDoubleClicked() ???
    void planetDoubleClicked(GameItemRow * planetItem);	/**< Selects planet from list of available planets. */
    void systemDoubleClicked(GameItemRow * planetItem); /**< Selects solar system from list of available solar systems. */
    void ownedShipDoubleClicked(GameItemRow * planetItem);  /**< Selects ship from list of owned ships. */
    void enemyShipDoubleClicked(GameItemRow * planetItem);	 /**< Selects ship from list of near enemy ships. */
	void distantEnemyShipDoubleClicked(GameItemRow * planetItem); /**< Selects ship from list of far enemy ships. */
	
	void setShipJourneyDetails(ShipJourneyDetailsFAIL & details);	/**< Set and displays jorney details of selected ship. */
	void setShipJourneyDetails(ShipJourneyDetailsSTANDARD & details);	/**< Set and displays jorney details of selected ship. */
	void setShipJourneyDetails(ShipJourneyDetailsPURSUIT & details);	/**< Set and displays jorney details of selected ship. */
	void setShipJourneyDetails(ShipJourneyDetailsMOVE_TO & details);	/**< Set and displays jorney details of selected ship. */
	void setShipJourneyDetails(ShipJourneyDetailsMOVE_TO_SPACE_OBJECT & details);	/**< Set and displays jorney details of selected ship. */

	void setNavigationState(NavigationStatus & navigationStatus);	/**< Set and displays navigation state of selected ship. */
	
	/* Answers from server */
	//TODO, FIXME, COMMENT ME
	void answerNavigationMoveToSpaceObject();
	void answerNavigationMoveToSpaceObjectByWarp();
	void answerNavigationMoveTo();
	void answerNavigationPursuit();
	void answerNavigationBreakWarp();
	void answerNavigationOrbit();
	void answerNavigationStop();	
	void answerNavigationWarp();
	void answerNavigationDockDown(id_t shipId, id_t baseId, DockingResult result);	
	void answerNavigationUnbound(id_t shipId, DockingResult result);

	void answerNavigationMoveToSpaceObjectFAIL();
	void answerNavigationMoveToSpaceObjectByWarpFAIL();
	void answerNavigationMoveToFAIL();
	void answerNavigationPursuitFAIL();
	void answerNavigationBreakWarpFAIL();
	void answerNavigationOrbitFAIL();
	void answerNavigationStopFAIL();	
	void answerNavigationWarpFAIL();

	void clearAllPlanets();

	static std::wstring dockingResult2WString(DockingResult result);
	bool isInWarp();
private slots:
    void submitCustomClickedSlot();
    void stopButtonClickedSlot();
	void breakWarpButtonClickedSlot();
    void orbitButtonClickedSlot();	
public slots:	
	void cancelNavigationSlot();
	void moveStandardNavigationDialogSlot();
	void moveSubspaceNavigationDialogSlot();
	void dockDownNavigationDialogSlot();
	void unboundSlot();
	void rejectDialogSlot();
private:
    void clearContent();

	void setActualPosition(position_t positionX, position_t positionY);
	void setTargetPosition(const std::string &targetSpaceObjectName);
	void setTargetPosition(position_t positionX, position_t positionY);
	void setEstimationTime(unsigned long long estimationTimeInSeconds);
	void setEstimationDistance(unsigned long long estimationDistanceInKilometers);
	void setSpeed(unsigned long long speedInMetersPerSecond);
	void setAcceleration(unsigned long long accelerationInMetersPerSquaredSecond);
	void setTargetAction(const std::string & action);
	void setCurrentAction(const std::string & action);
	void setMovementState(const std::string & action);
	void setDockingResult(bool isDockedInBase, DockingResult result);

	unsigned long recalcTimeInput(bool & successStatus);

	void clearJourneyDetails();

	std::string createPosition(position_t positionX, position_t positionY);
	void showNavigationDialog(bool showWarp);
	void showNavigationDialog(DockingResult canDockDown);
	void showNavigationDialog(const NavigationPlanetDetails & planet);

	void updateWarpInformation(const std::string & state);

	ENavigationType navigateTo_;
	GameItemRow * selectedItem_;
	position_t positionx;
	position_t positiony;

    Ui::NavigationWidget ui_;

    PlanetsTable* planetsTable_;
	SystemsTable* systemsTable_;
    LocationTable* enemyShipsTable_;
	LocationTable* distantEnemyShipsTable_;
    LocationTable* ownedShipsTable_;

	std::map<id_t, NavigationPlanetDetails> planets_;

    SimpleItem contextShip_;
	id_t targetSpaceObjectId_;
	id_t targetFortressId_;
	id_t selectedSunId_;

	bool isInWarp_;

	NavigationDialog * navigationDialog_;

	QRegExpValidator * coordXValidator_;
	QRegExpValidator * coordYValidator_;

	EShipMovementState shipMovementState_;

	void changeMovementState(EShipMovementState movementState);

    CommandClient * client_;

    void clearFilteredPlanets();
    void clearFilteredSystems();
    void clearFilteredOwnedShips();
    void clearFilteredEnemyShips();
    
    void clearAllSystems();
    void clearAllOwnedShips();
    void clearAllEnemyShips();
	void clearAllDistantEnemyShips();

	void setActualIdToSpaceObject(id_t actualId);
	void setActualIdToFortress(id_t actualId);
	void clearActualIdToAll();

	void setTargetIdToSpaceObject(id_t targetId);
	void setTargetIdToFortress(id_t targetId);
	void updateFortressTargetID(id_t targetId);
	void updateSpaceObjectTargetID(id_t targetId);

	void clearTargetIdToAll();

	void createNavigationDialog();
	void submitNavigation(bool canDockDown, bool canDockUp);
signals:
	void navigationMoveToSpaceObjectSignal(unsigned long shipId, unsigned long spaceObjectId, unsigned long seconds);
	void navigationMoveToSpaceObjectByWarpSignal(unsigned long shipId, unsigned long spaceObjectId);
	
	void navigationMoveToSignal(unsigned long shipId, position_t positionx, position_t positiony, unsigned long seconds);
	void navigationPursuitSignal(unsigned long shipId, unsigned long spaceObjectId, unsigned long seconds);
	void navigationBreakWarpSignal(unsigned long shipId);
	void navigationOrbitSignal(unsigned long shipId);
	void navigationStopSignal(unsigned long shipId);	
	void navigationWarpSignal(unsigned long shipId, position_t positionx, position_t positiony);
	void navigationPlanetsInSystemSignal(id_t shipId);
	void navigationDockDownSignal(id_t baseId);
	void navigationUnboundSignal();

	/** Signals that widget wants to show dialog */
	void showDialogSignal();

	/** Signals that widget wants to hide dialog */
	void hideDialogSignal();
};

#endif
