#ifndef LOCATION_TABLE_H
#define LOCATION_TABLE_H

#include <QWidget>
#include <QLineEdit>
#include <QPushButton>
#include <QTableWidget>
#include <QLabel>
#include <qstyleditemdelegate.h>
#include <qpainter.h>
#include <map>

#include "softProj\DetailsWidget\SimpleItem.h"
#include "protocol.h"
#include "softProj\clientServer\structs.h"

enum EGameItemType {
    GAME_ITEM_SHIP, GAME_ITEM_BASE, GAME_ITEM_PLANET, GAME_ITEM_SYSTEM,
};

class GameItemRow {
private:
	EGameItemType type_;
public:
    virtual QString getName() const = 0;
	virtual double getDistance() const = 0;
	virtual id_t getId() = 0;

	EGameItemType getType() {
		return type_;
	}

    GameItemRow(EGameItemType type) {
		this->type_ = type;
	}	
};

class NavigationObjectRow : public GameItemRow {
private:
	NavigationObject item_;
public:
    QString getName() const {
		return QString::fromUtf8(item_.name.c_str());
    }

    double getDistance() const {
		return item_.distance;
    }

	id_t getId() {
		return item_.id;
	}

    NavigationObjectRow(const NavigationObject & item, EGameItemType type) : GameItemRow(type) {
        this->item_ = item;
    }  

	EGameItemType type;
};

class NavigationBaseObjectRow : public GameItemRow {
private:
	NavigationBaseObject item_;
public:
    QString getName() const {
		return QString::fromUtf8(item_.name.c_str());
    }

    double getDistance() const {
		return item_.distance;
    }

	id_t getId() {
		return item_.id;
	}

    NavigationBaseObjectRow(const NavigationBaseObject & item, EGameItemType type) : GameItemRow(type) {
        this->item_ = item;
    }  

	DockingResult canShipDockDown() {
		return item_.canShipDockDown;
	}

	EGameItemType type;
};

class HighResolutionRow : public GameItemRow {
private:
	NavigationHighResolutionDetails item_;
public:
    QString getName() const {
		return QString::fromUtf8(item_.fortressName.c_str());
    }

    double getDistance() const {
		return item_.distance;
    }

	id_t getId() {
		return item_.shipId;
	}

    HighResolutionRow(const NavigationHighResolutionDetails & item, EGameItemType type) : GameItemRow(type) {
        this->item_ = item;
    }    

	std::string getRealmName() {
		return item_.fortressRealm;
	}
};

class LongRangeRow : public GameItemRow {
private:
	NavigationLongRangeDetails item_;
public:
    QString getName() const {
		return "";
    }

    double getDistance() const {
		return item_.distance;
    }

	id_t getId() {
		return item_.shipId;
	}

    LongRangeRow(const NavigationLongRangeDetails & item, EGameItemType type) : GameItemRow(type) {
        this->item_ = item;
    }    
};

class NavigationWidget;

class LocationTable : public QWidget {
    Q_OBJECT

public:
    LocationTable(NavigationWidget *parent);

    void setTitleLabel(QLabel *titleLabel);
    void setTable(QTableWidget *tableWidget);
    void setSearchButton(QPushButton *searchButton);
    void setShowAllButton(QPushButton *showAllButton);
    void setSearchEdit(QLineEdit *searchEdit);

    void clearFilteredContentKeepFilter();
    void clearAllContentKeepFilter();
    void insertItem(GameItemRow *row);       
    void connectSignals();	

	void setTitleText(const std::wstring & text);

	void setActualId(id_t actualId);
	void setTargetId(id_t actualId);
	void setSystemId(id_t systemId);
	void refreshRowsColor();

	void updateItems(std::map<id_t, GameItemRow *> & newItems);
	id_t getCurrentID();
protected:        
    GameItemRow * findItemRow(int row, int col);

    virtual void cellClicked(GameItemRow *);
    virtual void cellDoubleClicked(GameItemRow *);

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

	id_t currentActualId_;
	id_t currentTargetId_;
	id_t currentSystemId_;

    NavigationWidget * navigationWidget_;

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

    virtual int insertItemIntoTable(GameItemRow * item);	

    std::map<id_t, GameItemRow *> rows_;
	QRegExp * currentFilter_;
	void clearFilterString();
	bool matchesFilterIfAny(const QString & name);
private slots:
    void cellDoubleClickedSlot(int row, int col);   
    void cellClickedSlot(int row, int col);
private slots:
    void searchClickedSlot();
    void showAllClickedSlot();
};

class PlanetsTable : public LocationTable {
public:
    PlanetsTable(NavigationWidget *parent);
	void setSunText(const std::string & text);
private:
    virtual void cellDoubleClicked(GameItemRow * destination);
    virtual int insertItemIntoTable(GameItemRow * row);
};

class EnemyShipsTable : public LocationTable {
public:
    EnemyShipsTable(NavigationWidget *parent);
private:
    virtual void cellDoubleClicked(GameItemRow * destination);
    virtual int insertItemIntoTable(GameItemRow * row);
};

class DistantEnemyShipsTable : public LocationTable {
public:
    DistantEnemyShipsTable(NavigationWidget *parent);
private:
    virtual void cellDoubleClicked(GameItemRow * destination);
    virtual int insertItemIntoTable(GameItemRow * row);
};

class OwnedShipsTable : public LocationTable {
public:
    OwnedShipsTable(NavigationWidget *parent);
private:
    virtual void cellDoubleClicked(GameItemRow * destination);
    virtual int insertItemIntoTable(GameItemRow * row);
};

class SystemsTable : public LocationTable {
public:
    SystemsTable(NavigationWidget *parent);
private:
    virtual void cellDoubleClicked(GameItemRow * destination);
    virtual void cellClicked(GameItemRow * destination);
    virtual int insertItemIntoTable(GameItemRow * row);	
};

enum ENavigationType {
	NAVIGATION_SYSTEM,
	NAVIGATION_PLANET,
	NAVIGATION_CUSTOM,
	NAVIGATION_SHIP,
	NAVIGATION_BASE,
};

class BackgroundDelegate : public QStyledItemDelegate
{
public:
    explicit BackgroundDelegate(QObject *parent = 0)
        : QStyledItemDelegate(parent)
    {
    }
    void paint(QPainter *painter, const QStyleOptionViewItem &option,
               const QModelIndex &index) const
    {
        // Fill the background before calling the base class paint
        // otherwise selected cells would have a white background
        QVariant background = index.data(Qt::BackgroundRole);

        if (background.canConvert<QBrush>())
            painter->fillRect(option.rect, background.value<QBrush>());
        
        QStyledItemDelegate::paint(painter, option, index);       
    }
};

#endif