#include "AdvancedTableView.h"

#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QHeaderView>
#include <QScrollBar>
#include <QSqlQueryModel>
#include <QMenu>


#if _MSC_VER >= 1600
#pragma execution_character_set("utf-8")
#endif


#define SELECTED_VIEW_DEFAULT_WIDTH		200					// 选择区默认宽度
#define ROLE_PK							Qt::UserRole+1		// Role主键

AdvancedTableView::AdvancedTableView(QWidget *parent)
	: QTableView(parent)
	, wgtContainer(nullptr)
	, twSelected(nullptr)
	, lblCounter(nullptr)
	, btnExpand(nullptr)
	, btnCollapse(nullptr)
	, selectedViewState(Normal)
	, multipleSelect(false)
	, inited(false)
	, selectedRecords(nullptr)
{
	// 设置默认样式
	horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
	setSelectionBehavior(QAbstractItemView::SelectRows);
	setAlternatingRowColors(true);
}

AdvancedTableView::~AdvancedTableView()
{
	if (selectedRecords != nullptr)
	{
		delete selectedRecords;
		selectedRecords = nullptr;
	}
	delete 	btnExpand;
		delete btnCollapse;
}			   	

void AdvancedTableView::setMultipleSelect(bool value)
{
	if (value)
	{
		init();
		wgtContainer->show();
		multipleSelect = true;
	}
	else
	{
		//wgtContainer->hide();
		multipleSelect = false;
	}
}

const QStringList AdvancedTableView::getSelectedPKs()
{
	QStringList retval;

	Q_ASSERT(!pkFieldName.isEmpty());

	if (selectedRecords == nullptr)
		return retval;

	for (size_t i = 0; i < selectedRecords->length(); i++)
	{
		retval << selectedRecords->at(i).value(pkFieldName).toString();
	}

	return retval;
}

const QVariant AdvancedTableView::getSelectedPK()
{
	Q_ASSERT(!pkFieldName.isEmpty());

	QVariant result;
	QModelIndexList list = selectedIndexes();
	if (list.count() <= 0)
		return result;

	QModelIndex index = this->selectionModel()->currentIndex();
	QSqlQueryModel* sqm = (QSqlQueryModel*)model();
	QSqlRecord record = sqm->record(index.row());
	return record.value(pkFieldName);
}

const QSqlRecord AdvancedTableView::getSelectedRecord()
{
	QSqlRecord result;
	QModelIndexList list = selectedIndexes();
	if (list.count() <= 0)
		return result;

	QModelIndex index = this->selectionModel()->currentIndex();
	QSqlQueryModel* sqm = (QSqlQueryModel*)model();
	result = sqm->record(index.row());

	return result;
}

void AdvancedTableView::resizeEvent(QResizeEvent *event)
{
	if (wgtContainer != nullptr)
	{
		wgtContainer->setGeometry(width() - SELECTED_VIEW_DEFAULT_WIDTH, 0, SELECTED_VIEW_DEFAULT_WIDTH, height());
		selectedViewState = Normal;
	}

	//this->update();
	QTableView::resizeEvent(event);
}

void AdvancedTableView::setModel(QAbstractItemModel *model)
{
	QTableView::setModel(model);

	if (twSelected != nullptr)
	{
		cloneHeaderLabels();
		connect(model, SIGNAL(checkStateChanged(Qt::CheckState, const QSqlRecord &)), this, SLOT(checkStateChanged(Qt::CheckState, const QSqlRecord &)), Qt::UniqueConnection);
	}
}

void AdvancedTableView::checkStateChanged(Qt::CheckState state, const QSqlRecord &record)
{
	switch (state)
	{
	case Qt::Unchecked:
		unselectRecord(record);
		break;
	case Qt::PartiallyChecked:
		break;
	case Qt::Checked:
		selectRecord(record);
		break;
	}
}

void AdvancedTableView::expandSelectedView()
{
	if (selectedViewState == Normal)
	{
		int w = width() / 2;
		wgtContainer->setGeometry(w, 0, w, height());
		selectedViewState = Max;
	}
	else if (selectedViewState == Min)
	{
		wgtContainer->setGeometry(width() - SELECTED_VIEW_DEFAULT_WIDTH, 0, SELECTED_VIEW_DEFAULT_WIDTH, height());
		selectedViewState = Normal;
		twSelected->show();
	}
}

void AdvancedTableView::collapseSelectedView()
{
	if (selectedViewState == Normal)
	{
		int w = 25;
		if (verticalScrollBar()->isVisible())
			w += verticalScrollBar()->width() + 10;

		wgtContainer->setGeometry(width() - w, 0, w, height());
		selectedViewState = Min;
		twSelected->hide();
	}
	else if (selectedViewState == Max)
	{
		wgtContainer->setGeometry(width() - SELECTED_VIEW_DEFAULT_WIDTH, 0, SELECTED_VIEW_DEFAULT_WIDTH, height());
		selectedViewState = Normal;
	}
}

void AdvancedTableView::removeRow()
{
	if (twSelected == nullptr)
		return;

	QModelIndex index = twSelected->currentIndex();
	twSelected->removeRow(index.row());
	if (selectedRecords != nullptr)
		selectedRecords->remove(index.row());

	lblCounter->setText(QString::number(twSelected->rowCount()));
	if (twSelected->rowCount() == 0)
		lblCounter->hide();
}

void AdvancedTableView::init()
{
	if (inited)
		return;

	wgtContainer = new QWidget(this);
	QHBoxLayout *layout = new QHBoxLayout(this);
	QVBoxLayout *layoutButtn = new QVBoxLayout(this);
	layout->setContentsMargins(0, 0, 0, 0);
	layout->setSpacing(0);
	layoutButtn->setContentsMargins(0, 0, 0, 3);
	layoutButtn->setSpacing(3);
	wgtContainer->setLayout(layout);

	lblCounter = new QLabel(this);
	//btnExpand = new QPushButton(this);
	//btnCollapse = new QPushButton(this);
	btnExpand = new QPushButton();
	btnCollapse = new QPushButton();
	btnExpand->setToolTip("展开");
	btnCollapse->setToolTip("收起");
	//btnExpand->setFixedSize(25, 16);
	//btnCollapse->setFixedSize(25, 16);

	lblCounter->setAlignment(Qt::AlignCenter);
	lblCounter->setFixedSize(20, 20);
	lblCounter->setStyleSheet("QLabel{ border-radius:10px; border:1px solid gray; background-color:white; font-size:10px; }");
	lblCounter->hide();
	btnExpand->setStyleSheet("QPushButton{border-image:url(resources/arrow_left.png); background-color:white;min-width:25;min-height:16; } QPushButton:hover{border-image:url(resources/arrow_left_hover.png)}");
	btnCollapse->setStyleSheet("QPushButton{border-image:url(resources/arrow_right.png); background-color:white; min-width:25;min-height:16;}  QPushButton:hover{border-image:url(resources/arrow_right_hover.png)}");

	layoutButtn->addStretch();
	layoutButtn->addWidget(lblCounter);
	layoutButtn->addWidget(btnExpand);
	layoutButtn->addWidget(btnCollapse);
	layoutButtn->addSpacing(16);
	connect(btnExpand, &QPushButton::pressed, this, &AdvancedTableView::expandSelectedView);
	connect(btnCollapse, &QPushButton::pressed, this, &AdvancedTableView::collapseSelectedView);

	twSelected = new QTableWidget(this);
	twSelected->setEditTriggers(QAbstractItemView::NoEditTriggers);
	twSelected->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
	twSelected->setSelectionBehavior(QAbstractItemView::SelectRows);
	twSelected->setAlternatingRowColors(true);
	twSelected->setContextMenuPolicy(Qt::CustomContextMenu);
	twSelected->verticalHeader()->hide();

	QMenu *menu = new QMenu(this);
	menu->addAction("删除", this, SLOT(removeRow()));
	connect(twSelected, &QTableView::customContextMenuRequested, [=](const QPoint &){
		menu->exec(QCursor::pos());
	});

	layout->addLayout(layoutButtn);
	layout->addWidget(twSelected);

	wgtContainer->raise();


	selectedRecords = new QVector<QSqlRecord>;

	inited = true;
}

void AdvancedTableView::cloneHeaderLabels()
{
	QStringList headers;
	for (int i = 0; i < model()->columnCount(); i++)
	{
		headers.append(model()->headerData(i, Qt::Horizontal).toString());
	}

	twSelected->setColumnCount(headers.count());
	twSelected->setHorizontalHeaderLabels(headers);
}

void AdvancedTableView::selectRecord(const QSqlRecord &record)
{
	if (twSelected == nullptr)
		return;

	Q_ASSERT(!pkFieldName.isEmpty());

	// 检查是否存在
	for (size_t i = 0; i < twSelected->rowCount(); i++)
	{
		QTableWidgetItem *item = twSelected->item(i, 0);
		if (item->data(ROLE_PK) == record.value(pkFieldName))
		{
			return;
		}
	}

	int row = twSelected->rowCount();
	twSelected->setRowCount(row + 1);

	for (int col = 0; col < model()->columnCount(); col++)
	{
		QTableWidgetItem *item = new QTableWidgetItem(record.value(col).toString());
		twSelected->setItem(row, col, item);

		if (pkFieldName == record.fieldName(col))
		{
			item->setData(ROLE_PK, record.value(col));
		}
	}

	if (selectedRecords != nullptr)
		selectedRecords->append(record);

	lblCounter->setText(QString::number(twSelected->rowCount()));
	lblCounter->show();
}

void AdvancedTableView::unselectRecord(const QSqlRecord &record)
{
	if (twSelected == nullptr)
		return;

	Q_ASSERT(!pkFieldName.isEmpty());

	for (size_t i = 0; i < twSelected->rowCount(); i++)
	{
		QTableWidgetItem *item = twSelected->item(i, 0);
		if (item->data(ROLE_PK) == record.value(pkFieldName))
		{
			twSelected->removeRow(i);
			if (selectedRecords != nullptr)
				selectedRecords->remove(i);
			break;
		}

	}
	lblCounter->setText(QString::number(twSelected->rowCount()));
	if (twSelected->rowCount() == 0)
		lblCounter->hide();
}