#ifndef GENERIC_TABLE_UI_H
#define GENERIC_TABLE_UI_H


#include <QAbstractItemModel>
#include <QTableView>
#include <QItemDelegate>
#include <QFileInfo>
#include <QEvent>
#include <QMimeData>
#include <QDragEnterEvent>
#include "GenericTable.h"


class GenericTableView : public QTableView
{
public:
	GenericTableView() : QTableView(nullptr), m_genericTable(nullptr) {
		setDragDropMode(QAbstractItemView::InternalMove);
	}

	void init(GenericTableBase* a_table, QWidget* a_parent)
	{
		setParent(a_parent);
		m_genericTable = a_table;
		setAcceptDrops(m_genericTable->m_readOnly ? false : true);
	}

	void dragEnterEvent(QDragEnterEvent *event)
	{
		if (!m_genericTable->m_readOnly) {
			event->setDropAction(Qt::LinkAction);
			event->accept();
		}
	}

	void dropEvent(QDropEvent *event)
	{
		if (event->mimeData()->hasUrls() && !m_genericTable->m_readOnly)
		{
			QList<QUrl> urls = event->mimeData()->urls();
			for (int i = 0; i < urls.length(); i++)
			{
				m_genericTable->dropData(urls[i].toLocalFile().toUtf8());
			}
		}
		event->accept();
	}

	void currentChanged(const QModelIndex &current, const QModelIndex &previous)
	{
		m_genericTable->m_currentRow = current.row();
	}

private:
	GenericTableBase *m_genericTable;
};


class GenericTableUI : public QAbstractTableModel
{
public:
	GenericTableUI() : QAbstractTableModel(nullptr), m_genericTable(nullptr), m_view(nullptr)
	{
	}

	void init(GenericTableBase* a_table, QTableView* a_view)
	{
		setParent(a_view);
		m_genericTable = a_table;
		m_view = a_view;
		m_view->setModel(this);
		m_genericTable->RegisterCallbackOnChange(updateCallback, this);
		if (m_genericTable->m_columnNames.size())
		{
			//for (int i = 0; i < m_genericTable->m_columnNames.size() - 1; i++)
			//	m_view->horizontalHeader()->setSectionResizeMode(i, QHeaderView::ResizeToContents);
			m_view->horizontalHeader()->setSectionResizeMode((int)m_genericTable->m_columnNames.size() - 1, QHeaderView::Stretch);
		}
	}

	~GenericTableUI()
	{
	}

	/*
	void setItemDelegate(QAbstractItemDelegate* a_delegate)
	{
		//m_view->setItemDelegate(a_delegate);
	}
	*/

private:
	bool isValid(int row, int col) const
	{
		return (row >= 0 && col >= 0 && row < m_genericTable->size() && col < m_genericTable->m_columnNames.size()) ? true : false;
	}

	virtual Qt::ItemFlags flags(const QModelIndex &index) const
	{
		if (!index.isValid() || !isValid(index.row(), index.column()))
			return Qt::NoItemFlags;
		Qt::ItemFlags editable = m_genericTable->m_readOnly ? Qt::NoItemFlags : Qt::ItemIsEditable;
		editable = Qt::ItemIsEditable;
		QVariant::Type type = m_genericTable->m_columnTypes[index.column()];
		if (type == QVariant::Url)
			return Qt::ItemIsSelectable | Qt::ItemIsEnabled; // Make URLs non-editable
		if (type == QVariant::Bool)
			return editable | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled; // Make bools checkable
		return editable | Qt::ItemIsSelectable | Qt::ItemIsEnabled;
	}

	virtual int rowCount(const QModelIndex &parent = QModelIndex()) const
	{
		return (int)m_genericTable->size();
	}

	virtual int columnCount(const QModelIndex &parent = QModelIndex()) const
	{
		return (int)m_genericTable->m_columnNames.size();
	}

	virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const
	{
		if (role == Qt::DisplayRole && orientation == Qt::Horizontal && section < m_genericTable->m_columnNames.size())
		{
			return QString(m_genericTable->m_columnNames[section].c_str());
		}
		return QAbstractTableModel::headerData(section, orientation, role);
	}

	bool setData(const QModelIndex &index, const QVariant &value, int role)
	{
		if (!index.isValid() || !isValid(index.row(), index.column()))
			return false;
		m_genericTable->setValue(index.row(), index.column(), value);
		return true;
	}

	virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const
	{
		if (!index.isValid() || !isValid(index.row(), index.column()) || (role != Qt::DisplayRole && role != Qt::CheckStateRole) )
			return QVariant();
		return m_genericTable->value(index.row(), index.column());
	}

	void reload()
	{
		beginResetModel();
		endResetModel();
		beginInsertRows(QModelIndex(), 0, (int)m_genericTable->size());
		endInsertRows();
		m_view->scrollToBottom();
	}

	static void __cdecl updateCallback(void *a_data)
	{
		GenericTableUI* obj = (GenericTableUI*)a_data;
		obj->reload();
	}

private:
	QTableView *m_view;
	GenericTableBase *m_genericTable;
};


#endif // GENERIC_TABLE_UI_H
