/* This file is part of the Springlobby (GPL v2 or later), see COPYING */

#include "battledataviewmodel.h"

#include <wx/colour.h>

#include "gui/iconscollection.h"
#include "ibattle.h"
#include "utils/slpaths.h"
#include "useractions.h"

BattleDataViewModel::BattleDataViewModel()
	: BaseDataViewModel<IBattle>::BaseDataViewModel(COLUMN_COUNT)
{
}

BattleDataViewModel::~BattleDataViewModel() {
}

void BattleDataViewModel::GetValue(wxVariant& variant,
		const wxDataViewItem& item, unsigned int col) const {

	const IBattle* battle = static_cast<const IBattle*>(item.GetID());

	wxASSERT(battle != nullptr);

	IconsCollection* iconsCollection = IconsCollection::Instance();

    /* In case if wxGTK will try to render invalid item */
    if (battle == nullptr || ContainsItem(*battle) == false) {

        switch (col) {
        case STATUS:
        case COUNTRY:
        case RANK:
            variant = wxVariant(iconsCollection->BMP_EMPTY);
            break;

        case MAP:
        case GAME:
        case ENGINE:
            variant = wxVariant(wxDataViewIconText(wxEmptyString));
            break;

        case DESCRIPTION:
        case HOST:
        case SPECTATORS:
        case PLAYERS:
        case MAXIMUM:
        case RUNNING:
        case DEFAULT_COLUMN:
        default:
            variant = wxVariant(wxEmptyString);
        }
        return;
    }

    const BattleOptions& opts = battle->GetBattleOptions();

	switch (col) {
	case STATUS:
		variant = wxVariant(iconsCollection->GetBattleStatusBmp(*battle));
		break;

	case COUNTRY:
		variant = wxVariant(iconsCollection->GetFlagBmp(battle->GetFounder().GetCountry()));
		break;

	case RANK:
		variant = wxVariant(iconsCollection->GetRankBmp(battle->GetRankNeeded(), false));
		break;

	case DESCRIPTION:
		variant = wxVariant(wxString(opts.description));
		break;

	case MAP:
		variant = wxVariant(wxDataViewIconText(wxString(battle->GetHostMapName()), battle->MapExists(false) ? iconsCollection->ICON_EXISTS : iconsCollection->ICON_NEXISTS));
		break;

	case GAME:
		variant = wxVariant(wxDataViewIconText(wxString(battle->GetHostGameName()), battle->GameExists(false) ? iconsCollection->ICON_EXISTS : iconsCollection->ICON_NEXISTS));
		break;

	case HOST:
		variant = wxVariant(wxString(opts.founder));
		break;

	case SPECTATORS:
		variant = wxVariant(wxString::Format(_T("%d"), battle->GetSpectators()));
		break;

	case PLAYERS:
		variant = wxVariant(wxString::Format(_T("%d"), (static_cast<int>(battle->GetNumUsers()) - battle->GetSpectators())));
		break;

	case MAXIMUM:
		variant = wxVariant(wxString::Format(_T("%d"), static_cast<int>(battle->GetMaxPlayers())));
		break;

	case RUNNING:
		variant = wxVariant((wxTimeSpan(0 /*h*/, 0 /*m*/,
				   battle->GetBattleRunningTime()).Format(_T("%H:%M"))));
		break;

	case ENGINE:
		variant = wxVariant(wxDataViewIconText(wxString(battle->GetEngineVersion()),
				SlPaths::GetCompatibleVersion(battle->GetEngineVersion()).empty() ? iconsCollection->ICON_NEXISTS : iconsCollection->ICON_EXISTS));
		break;

	case DEFAULT_COLUMN:
		//Do nothing
		break;

	default:
		wxASSERT(false);
	}
}

int BattleDataViewModel::Compare(const wxDataViewItem& itemA,
		const wxDataViewItem& itemB, unsigned int column,
		bool ascending) const {

	const IBattle* battleA = static_cast<const IBattle*>(itemA.GetID());
	const IBattle* battleB = static_cast<const IBattle*>(itemB.GetID());

	wxASSERT(battleA != nullptr);
	wxASSERT(battleB != nullptr);

	int sortingResult;

	switch (column) {
	case STATUS:
	{
		int b1 = 0, b2 = 0;

		if (battleA->GetNumActivePlayers() == 0)
			b1 += 2000;
		if (battleB->GetNumActivePlayers() == 0)
			b2 += 2000;
		if (battleA->GetInGame())
			b1 += 1000;
		if (battleB->GetInGame())
			b2 += 1000;
		if (battleA->IsLocked())
			b1 += 100;
		if (battleB->IsLocked())
			b2 += 100;
		if (battleA->IsPassworded())
			b1 += 50;
		if (battleB->IsPassworded())
			b2 += 50;
		if (battleA->IsFull())
			b1 += 25;
		if (battleB->IsFull())
			b2 += 25;

		// inverse the order
		if (b1 < b2) {
			sortingResult = -1;
		} else if (b1 > b2) {
			sortingResult = 1;
		} else {
			sortingResult = 0;
		}
	}
		break;

	case COUNTRY:
		if (battleA->GetFounder().GetCountry() < battleB->GetFounder().GetCountry()) {
			sortingResult = -1;
		} else if (battleA->GetFounder().GetCountry() > battleB->GetFounder().GetCountry()) {
			sortingResult = 1;
		} else {
			sortingResult = 0;
		}
		break;

	case RANK:
		sortingResult = (battleA->GetRankNeeded() - battleB->GetRankNeeded());
		break;

	case DESCRIPTION:
	case HOST:
	case RUNNING:
		return BaseDataViewModel::Compare(itemA, itemB, column, ascending);
		break;

	case MAP:
		sortingResult = battleA->GetHostMapName().compare(battleB->GetHostMapName());
		break;

	case GAME:
		sortingResult = battleA->GetHostGameName().compare(battleB->GetHostGameName());
		break;

	case ENGINE:
		sortingResult = battleA->GetEngineVersion().compare(battleB->GetEngineVersion());
		break;

	case SPECTATORS:
		sortingResult = battleA->GetSpectators() - battleB->GetSpectators();
		break;

	case MAXIMUM:
		sortingResult = battleA->GetMaxPlayers() - battleB->GetMaxPlayers();
		break;

	case PLAYERS:
	{
		int playersA = battleA->GetNumPlayers() - battleA->GetSpectators();
		int playersB = battleB->GetNumPlayers() - battleB->GetSpectators();
		sortingResult = playersA - playersB;
	}
	break;

	case DEFAULT_COLUMN:
		sortingResult = 0;
		break;

	default:
		wxASSERT(false);
		sortingResult = 0;
	}

	//Return direct sort order or reversed depending on ascending flag
	return ascending ? sortingResult : (sortingResult * (-1));
}

bool BattleDataViewModel::GetAttr(const wxDataViewItem& item,
		unsigned int, wxDataViewItemAttr& attr) const {

	const IBattle* battle = static_cast<const IBattle*>(item.GetID());

	wxASSERT(battle != nullptr);

    if (battle == nullptr || ContainsItem(*battle) == false) {
        return false;
    }

	//If founder is cause of highlight
	wxString groupName = useractions().GetGroupOfUser(battle->GetFounder().GetNick());
	if (groupName != wxEmptyString) {
		wxColour color = useractions().GetGroupHLColor(groupName);
		attr.SetBackgroundColour(color);
		return true;
	//If user is cause of highlight
	} else {
		for (unsigned int i = 0; i < battle->GetNumUsers(); ++i) {
			groupName = useractions().GetGroupOfUser(battle->GetUser(i).GetNick());
			if (groupName != wxEmptyString) {
				wxColour color = useractions().GetGroupHLColor(groupName);
				attr.SetBackgroundColour(color);
				return true;
			}
		}
	}
	return false;
}

wxString BattleDataViewModel::GetColumnType(unsigned int column) const {

	wxString colTypeString;

	switch (column) {
	case STATUS:
	case COUNTRY:
	case RANK:
		colTypeString = COL_TYPE_BITMAP;
		break;


	case MAP:
	case GAME:
	case ENGINE:
		colTypeString = COL_TYPE_ICONTEXT;
		break;

	case DESCRIPTION:
	case HOST:
	case RUNNING:
	case SPECTATORS:
	case MAXIMUM:
	case PLAYERS:
	case DEFAULT_COLUMN:
		colTypeString = COL_TYPE_TEXT;
		break;

	default:
		wxASSERT(false);
		colTypeString = COL_TYPE_TEXT;
	}

	return colTypeString;
}
