#ifndef FIGHT_WIDGET_H
#define FIGHT_WIDGET_H

#include <QtGui>
#include "ui_fightWidget.h"
#include "fightWidgetRow.h"
#include "fightWidgetRowWidget.h"
#include "softProj\clientServer\structs.h"
#include "softProj\Main\MessageDialog.h"
#include "softProj\Main\ConfirmDialog.h"
#include <deque>
#include <map>
#include <set>
#include "softProj\Main\INotifyUpdate.h"

class FightWidget;

enum EFortressFightTableType {
	FORTRESS_FIGHT_TABLE_OWNED, FORTRESS_FIGHT_TABLE_ENEMY
};

class FortressFightTable : public QWidget {
    Q_OBJECT

public:
    FortressFightTable(FightWidget* parent, EFortressFightTableType tableType);

    void setTitle(QPushButton *titleLabel); /**< Sets title name of the trade widget. */
    void setTable(QTableWidget *tableWidget);
    void setSearchButton(QPushButton *searchButton); //TODO, FIXME, COMMENTME
    void setShowAllButton(QPushButton *showAllButton); //TODO, FIXME, COMMENTME
    void setSearchEdit(QLineEdit *searchEdit); //TODO, FIXME, COMMENTME

    void clearFilteredContent();
    void clearAllContent();
    FightWidgetRowWidget * insertItem(FightWidgetRow *row);       
    void connectSignals();

	int findRowOfItem(unsigned long id);
	FightWidgetRow * findItemRow(int row, int col);
	FightWidgetRow * findItemById(id_t id);
	FightWidgetRowWidget * findRowWidgetById(id_t id);

	void removeRow(int row);
	void removeRowAndItem(FightWidgetRow * item, int row);		
	void removeRowAndItemById(id_t itemID);

	void setRowAsClicked(int row);
	void setNoRowAsClicked();
	FightWidgetRowWidget * getClickedRow();
protected:            	
    virtual void cellClicked(FightWidgetRow * item, int row);
	virtual void cellDoubleClicked(FightWidgetRow * item, int row);

    QPushButton *titleLabel_;
    QTableWidget *tableWidget_;
    QPushButton *searchButton_;
    QPushButton *showAllButton_;
    QLineEdit *searchEdit_;

    FightWidget * tradeWidget_;

    typedef std::map<QString, FightWidgetRow *> ItemsMap;
    typedef std::vector<FightWidgetRow *> ItemsVector;

    FightWidgetRowWidget * insertItemIntoTable(FightWidgetRow * item);

    std::map<long, FightWidgetRow *> rows_;

	FightWidgetRowWidget * clickedFortressRow_;	
private slots:
    void cellClickedSlot(int row, int col);
	void itemClickedSlot(id_t itemId);	
	void itemDoubleClickedSlot(id_t itemId);
private slots:
    void searchClickedSlot();
    void showAllClickedSlot();
private:	
	EFortressFightTableType tableType_;
};

struct fight_enemy_data {
	id_t selfFortressId;
	std::string selfFortressName;

	id_t fortressId;
	std::string fortressName;
	std::string realmName;
	bool isShip;
};

struct fortress_under_attack_data {
	id_t fortressID;
	std::string fortressName;
	int attackerCount;
};

class FightWidget : public NotifyWidget {
	Q_OBJECT
public:
	FightWidget(QWidget *parent);
	~FightWidget();

	/** Clears client state of the widget */
	void clearState();
private:
	Ui::FightWidget ui_;

	FortressFightTable * ownedFortressesTable_;
	FortressFightTable * enemyFortressesTable_;

	id_t getSelectedOwnedFortressID();

	void attackReportToFightEnemyData(const fight_action_report & report, fight_enemy_data & enemyData);
	void attackInformationToFightEnemyData(const fortress_attack_information & report, fight_enemy_data & enemyData);

	void refreshRow(FightWidgetRowWidget * rowWidget);
	void refreshOwnedRowById(id_t rowItemID);
	void refreshEnemyRowById(id_t rowItemID);

	/* FORTRESSES */
	void clearAllOwnedFortresses();
	void clearAllEnemyFortresses();

	FightWidgetRowWidget * insertOwnedFortress(FightWidgetRow * item);
	FightWidgetRowWidget * insertEnemyFortress(FightWidgetRow * item);	

	void setSelfPartner(FightWidgetRow * item);
	void setNoSelfPartner();

	void setPreparedPartner(FightWidgetRow * item);
	void setNoPreparedPartner();
	
	void setEnemyPartner(const fight_enemy_data & data) ;
	void setEnemyPartner(const fight_action_report & report) ;	
	void setNoEnemyPartner();

	bool isSynchronizing_;

	void refreshRows(id_t rowItemID1, id_t rowItemID2, id_t rowItemID3);

	std::map<id_t, id_t> allAttackingEnemyReports_;
	std::map<id_t, std::set<id_t>> allAttackingEnemyReportsByTargetFortress_;
	std::map<id_t, fight_enemy_data> attackingSelfReports_;
	std::map<id_t, fortress_under_attack_data> selfUnderAttackReportsList_;

	fortress_detailed_fight_data fightData_;

	void updateFortressFightData(const fortress_detailed_fight_data & fightData);
	void updateSelfUnderAttackList();

	void unsetClickedItemInEnemyTableIfNeccessary(id_t enemyID);
	void unsetClickedItemInOwnedTableIfNeccessary(id_t enemyID);

	void refreshAllRows();
public:	
	void ownedFortressClicked(FightWidgetRow * item, int row);
	void enemyFortressClicked(FightWidgetRow * item, int row);

	void ownedFortressDoubleClicked(FightWidgetRow * item, int row);
	void enemyFortressDoubleClicked(FightWidgetRow * item, int row);

	void setOwnedFortresses(const std::vector<fortress_attack_information> & items);
	void setEnemyFortresses(const fortress_attack_information & ownedFortress, const std::vector<SimpleItem> & ships, const std::vector<SimpleItem> & bases);
	void updateWeaponsInformation(id_t fortressId, weapons_status & state);

	id_t getSelfFortressId();

	void fightActionReport(const fight_action_report & report);
	void fightProgressReport(const fight_progress_report & report);
	void attackStartAcknowledgement(id_t selfFortressId, id_t enemyFortressId);
	void attackStopAcknowledgement(id_t selfFortressId);

	void setGameSecondsPerActualSecond(unsigned long value);
	void notifyUpdate();
private slots:
	void submitButtonClickedSlot();
	void cancelButtonClickedSlot();

	void submitWeaponsSlot(WeaponsChangeDetails & state);
	void resetWeaponsSlot();
signals:
	void fortressInWeaponsRangeSignal(id_t fortressId);
	void fortressWeaponsSettingsSignal(id_t fortressId);

	void attackFortressSignal(id_t selfFortressId, id_t enemyFortressId);
	void stopAttackFortressSignal(id_t selfFortressId);

	void submitWeaponsSignal(id_t fortressId, WeaponsChangeDetails & state);
	void resetWeaponsSignal(id_t fortressId);
	
	void updateAttackWarningsSignal(const std::map<id_t, fortress_under_attack_data> & fortresses);
	void removeFortressSignal(id_t fortressId, const std::string & fortressName);
};

#endif