#include "TradeWidget.h"
#include <cassert>
#include "softProj\settings.h"
#include "softProj\WeaponsWidget\fightWidgetRowWidget.h"
#include "../streams/ErrorStream.h"

extern KODIAK_DEBUG_STREAM KODIAK_DEBUG_COUT;

FortressTable::FortressTable(TradeWidget * parent, EFortressTableType tableType) : QWidget(parent) {
    titleLabel_ = 0;
    tableWidget_ = 0;
    searchButton_ = 0;
    searchEdit_ = 0;

    tradeWidget_ = parent;	
	this->tableType_ = tableType;

	clickedFortressRow_ = NULL;
}

void FortressTable::setTitle(QPushButton * titleLabel) {
    this->titleLabel_ = titleLabel;
}

void FortressTable::setTable(QTableWidget * tableWidget) {
    this->tableWidget_ = tableWidget;
	tableWidget_->verticalHeader()->setResizeMode(QHeaderView::Interactive);
}

void FortressTable::setSearchButton(QPushButton * searchButton) {
    this->searchButton_ = searchButton;
}

void FortressTable::setShowAllButton(QPushButton * showAllButton) {
    this->showAllButton_ = showAllButton;
}

void FortressTable::setSearchEdit(QLineEdit * searchEdit) {
    this->searchEdit_ = searchEdit;
}

void FortressTable::connectSignals() {
    bool isConnected = connect(searchButton_, SIGNAL(clicked()), this, SLOT(searchClickedSlot()));
    assert(isConnected);

    isConnected = connect(showAllButton_, SIGNAL(clicked()), this, SLOT(showAllClickedSlot()));
    assert(isConnected);

    isConnected = connect(tableWidget_, SIGNAL(cellClicked(int,int)), this, SLOT(cellClickedSlot(int, int)));
    assert(isConnected);    
}

void FortressTable::showAllClickedSlot() {
    clearFilteredContent();

	for (std::map<long, FortressItemRow *>::const_iterator it = rows_.begin(); it != rows_.end(); ++it) {
		insertItemIntoTable(it->second);
    }
}

void FortressTable::searchClickedSlot() {
    QString searchedString = searchEdit_->text();
    QRegExp rx(".*" + searchedString + ".*", Qt::CaseInsensitive);

    clearFilteredContent();

    ItemsVector matchedItems;

	for (std::map<long, FortressItemRow *>::const_iterator it = rows_.begin(); it != rows_.end(); ++it) {
		if (rx.exactMatch(it->second->getNameQString())) {
            matchedItems.push_back(it->second);
        }
    }

    for (ItemsVector::const_iterator it = matchedItems.begin(); it != matchedItems.end(); ++it) {
        insertItemIntoTable(*it);
    }
}

FightWidgetRowWidget * FortressTable::insertItem(FortressItemRow * item) {
    return insertItemIntoTable(item);
}

FightWidgetRowWidget * FortressTable::insertItemIntoTable(FortressItemRow * item) {
	
	tableWidget_->setSortingEnabled(false);

    const int targetRow = tableWidget_->rowCount();
    tableWidget_->insertRow(targetRow);

	rows_.insert(std::make_pair(item->getId(), item));

	FightWidgetRowWidget * itemWidget = new FightWidgetRowWidget(tableWidget_, item->getFortressType());

	if (item->isOwned()) {
		itemWidget->setAsGreen();
	}
	else {
		itemWidget->setAsBlue();
	}

	itemWidget->setItemName(item->getNameQString());
	itemWidget->setItemId(item->getId());

	bool connected = connect(itemWidget, SIGNAL(clickedSignal(id_t)), this, SLOT(itemClickedSlot(id_t)));

	assert(connected && "Signals not connected");

	tableWidget_->setRowHeight(targetRow, itemWidget->height());
	tableWidget_->setCellWidget(targetRow, 0, itemWidget);
    
	tableWidget_->setSortingEnabled(true);

    return itemWidget;
}

void FortressTable::clearFilteredContent() {
	clickedFortressRow_ = NULL;

    for (int i = tableWidget_->rowCount() - 1; i >= 0; --i) {
        tableWidget_->removeRow(i);
    }    
}

void FortressTable::removeRow(int row) {
	tableWidget_->removeRow(row);
}

void FortressTable::clearAllContent() {
    clearFilteredContent();
	rows_.clear();
}

void FortressTable::cellClickedSlot(int row, int col) {
	FortressItemRow * itemRow = findItemRow(row, col);

	if (itemRow == NULL) {
		KODIAK_DEBUG_COUT << "Item widget is NULL in void FortressTable::cellClickedSlot(int row, int col)";
		return;
	}

	cellClicked(itemRow, row);	
}

void FortressTable::cellClicked(FortressItemRow * item, int row) {
	switch (tableType_) {
	case FORTRESS_TABLE_OWNED:
		tradeWidget_->ownedFortressClicked(item, row);
		break;
	case FORTRESS_TABLE_SECOND_OWNED:
		tradeWidget_->ownedSecondFortressClicked(item, row);
		break;
	case FORTRESS_TABLE_ENEMY:
		tradeWidget_->enemyFortressClicked(item, row);
		break;
	}
}

FortressItemRow * FortressTable::findItemById(unsigned long id) {
    if (rows_.find(id) != rows_.end()) {
        return rows_[id];
    }
    else {
        return 0;
    }
}

FortressItemRow * FortressTable::findItemRow(int row, int) {
	FightWidgetRowWidget * itemRow = dynamic_cast<FightWidgetRowWidget *>(tableWidget_->cellWidget(row, 0));

	if (itemRow == NULL) {
		KODIAK_DEBUG_COUT << "Item widget is NULL in FortressItemRow * FortressTable::findItemRow(int row, int)";
		return 0;
	}

	id_t id = itemRow->getItemId();

    if (rows_.find(id) != rows_.end()) {
        return rows_[id];
    }
    else {
        return 0;
    }
}

void FortressTable::removeRowAndItem(FortressItemRow * item, int row) {
	rows_.erase(item->getId());
	removeRow(row);
}

int FortressTable::findRowOfItem(unsigned long id) {
	int rowCount = tableWidget_->rowCount();

	for (int row = 0; row < rowCount; ++row) {
		FightWidgetRowWidget * itemRow = dynamic_cast<FightWidgetRowWidget *>(tableWidget_->cellWidget(row, 0));

		if (itemRow == NULL) {
			KODIAK_DEBUG_COUT << "Item widget is NULL in int FortressTable::findRowOfItem(unsigned long id)";
			return -1;
		}

		int inspectedId = itemRow->getItemId();

		if (inspectedId == id) {
			return row;
		}
	}
	 
	return -1;
}

void FortressTable::itemClickedSlot(id_t itemId) {
	int row = findRowOfItem(itemId);
	FortressItemRow * itemRow = findItemById(itemId);

	if (itemRow == NULL) {
		KODIAK_DEBUG_COUT << "Item widget is NULL in void FortressTable::itemClickedSlot(id_t itemId)";
		return;
	}

	cellClicked(itemRow, row);
}

void FortressTable::setRowAsClicked(int row) {
	if (clickedFortressRow_ != NULL) {
		clickedFortressRow_->setAsClicked(false);
	}

	clickedFortressRow_ = dynamic_cast<FightWidgetRowWidget *>(tableWidget_->cellWidget(row, 0));

	if (clickedFortressRow_ == NULL) {
		return;
	}

	clickedFortressRow_->setAsClicked(true);
}

void FortressTable::setNoRowAsClicked() {
	if (clickedFortressRow_ != NULL) {
		clickedFortressRow_->setAsClicked(false);
		clickedFortressRow_ = NULL;
	}
}