/* LibraryTableView.cpp */

/* Copyright (C) 2011-2024 Michael Lugmair (Lucio Carreras)
 *
 * This file is part of sayonara player
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "TableView.h"

#include "Components/Library/PlayActionEventHandler.h"
#include "Gui/Library/Header/ColumnHeader.h"
#include "Gui/Library/Header/LibraryHeaderView.h"
#include "Gui/Library/ItemModel.h"
#include "Gui/Utils/GuiUtils.h"

#include "Utils/Algorithm.h"
#include "Utils/Logger/Logger.h"
#include "Utils/Set.h"

using namespace Library;

struct TableView::Private
{
	HeaderView* header;

	explicit Private(TableView* tableView) :
		header {new HeaderView(Qt::Horizontal, tableView)} {}
};

TableView::TableView(QWidget* parent) :
	ItemView(parent),
	m {Pimpl::make<Private>(this)}
{
	setHorizontalHeader(m->header);
	verticalHeader()->hide();
}

TableView::~TableView() = default;

void TableView::init(const PlayActionEventHandlerPtr& playActionEventHandler, LocalLibrary* library)
{
	auto headers = columnHeaders();
	m->header->init(headers, columnHeaderState(), sortorder(), autoResizeState());

	ItemView::init(playActionEventHandler);

	initView(library);

	Util::Algorithm::sort(headers, [](const auto& p1, const auto& p2) {
		return (p1->columnIndex() < p2->columnIndex());
	});

	connect(m->header, &QHeaderView::sectionCountChanged, this, &TableView::headerColumnsChanged);
	connect(m->header, &QHeaderView::sectionMoved, this, &TableView::sectionMoved);
	connect(m->header, &QHeaderView::sortIndicatorChanged, this, &TableView::sortorderChanged);
	connect(m->header, &HeaderView::sigAutoResizeToggled, this, &TableView::autoResizeTriggered);
	connect(m->header, &HeaderView::sigStateChanged, this, &TableView::saveColumnHeaderState);

	languageChanged();
}

void TableView::headerColumnsChanged(const int /*oldCount*/, const int /*newCount*/)
{
	const auto selectedIndexes = selectedItems();
	for(const auto index: selectedIndexes)
	{
		selectRow(index);
	}

	setupColumnNames();
}

void TableView::sortorderChanged(const int index, const Qt::SortOrder qtSortorder)
{
	if (!Util::between(index, columnHeaders().count()))
	{
		spLog(Log::Warning, this) << "Cannot apply sortorder, since the column count has changed between versions";
		return;
	}

	applySortorder(m->header->sortorder(index, qtSortorder));
}

void TableView::sectionMoved(const int /*logicalIndex*/, const int /*oldVisualIndex*/, const int /*newVisualIndex*/)
{
	setupColumnNames();
}

void TableView::autoResizeTriggered(const bool b)
{
	saveAutoResizeState(b);
	if(b)
	{
		m->header->resizeColumnsAutomatically();
	}
}

void TableView::setupColumnNames()
{
	const auto count = columnHeaders().count();
	for(int i = 0; i < count; i++)
	{
		const auto text = m->header->columnText(i);
		model()->setHeaderData(i, Qt::Horizontal, text, Qt::DisplayRole);
	}

	m->header->reloadColumnTexts();
}

void TableView::languageChanged()
{
	setupColumnNames();
}

int TableView::mapModelIndexToIndex(const QModelIndex& idx) const { return idx.row(); }

ModelIndexRange TableView::mapIndexToModelIndexes(const int idx) const
{
	return {
		model()->index(idx, 0),
		model()->index(idx, model()->columnCount() - 1)
	};
}

void TableView::skinChanged()
{
	ItemView::skinChanged();
	verticalHeader()->setDefaultSectionSize(Gui::Util::viewRowHeight(fontMetrics()));
}

void TableView::saveState()
{
	saveColumnHeaderState(m->header->saveState());
}
