#ifndef MINORI_GUI_WIDGETS_TEXT_H_
#define MINORI_GUI_WIDGETS_TEXT_H_

#include <QLineEdit>
#include <QPlainTextEdit>
#include <QSize>
#include <QWidget>
#include <QLabel>
#include <QVBoxLayout>
#include <QPointer>

#include <memory>
#include <unordered_map>

namespace TextWidgets {

/* These used to have getter methods to get the real Qt widgets;
 * don't make those anymore. Instead, add new methods that are
 * wrappers around the Qt methods instead. */

class Header : public QWidget {
	Q_OBJECT

public:
	Header(QWidget* parent = nullptr);
	void SetText(const std::string& title);

protected:
	QPointer<QLabel> title_;
	QPointer<QFrame> separator_;
};

class Label final : public QLabel {
	Q_OBJECT

public:
	Label(QWidget *parent = nullptr);
	Label(const QString &string, QWidget *parent = nullptr);
	void SetElidingMode(bool elide);

protected:
	void paintEvent(QPaintEvent *event) override;

private:
	bool elide_;
};

/* This is a nice clean wrapper around Label suitable for our needs. */
class Paragraph : public QWidget {
	Q_OBJECT

public:
	Paragraph(QWidget* parent = nullptr);
	void SetText(const std::string& text);
	void SetSelectable(bool enable);
	void SetWordWrap(bool enable);
	void SetElidingMode(bool enable);

protected:
	QPointer<QLabel> label_;
};

/* This aligns data with labels */
class LabelledParagraph final : public QWidget {
	Q_OBJECT

public:
	enum Style {
		BoldedLabels = (1 << 1),
		ElidedData = (1 << 2), /* does nothing for now */
	};

	LabelledParagraph(QWidget* parent = nullptr);
	~LabelledParagraph();
	void SetData(const std::vector<std::pair<std::string, std::string>>& data);
	void SetStyle(int style); /* bit-flags from Style enum */
	void Clear(void);

protected:
	QPointer<QWidget> contents_;
	QPointer<QGridLayout> contents_layout_;

	std::vector<std::pair<QSharedPointer<Label>, QSharedPointer<Label>>> data_;
};

/* this is just a generic QLabel with a specific font and foreground role,
 * which is why it's defined inline */
class Title final : public Paragraph {
public:
	Title(QWidget* parent = nullptr) : Paragraph(parent) {
		QFont fnt(label_->font());
		fnt.setPixelSize(16);
		label_->setFont(fnt);

		label_->setForegroundRole(QPalette::Highlight);
	}
};

/* ----------------------------------------------------------------------- */
/* Generic "Section" widget */

template<typename T>
class Section final : public QWidget {
public:
	Section(QWidget* parent = nullptr) : QWidget(parent) {
		header_ = new Header(this);

		content_container_ = new QWidget(this);
		content_ = new T(content_container_);

		QVBoxLayout* content_layout = new QVBoxLayout(content_container_);

		content_layout->addWidget(content_);
		content_layout->setSpacing(0);
		content_layout->setContentsMargins(12, 0, 0, 0);

		content_container_->setContentsMargins(0, 0, 0, 0);

		content_container_->setLayout(content_layout);

		QVBoxLayout* layout = new QVBoxLayout(this);

		layout->addWidget(header_);
		layout->addWidget(content_container_);
		layout->setSpacing(0);
		layout->setContentsMargins(0, 0, 0, 0);

		setLayout(layout);
	}

	Header& GetHeader() { return *header_; }
	T& GetContent() { return *content_; }

private:
	Header* header_;
	T* content_;

	/* I don't think making a separate container
	 * widget is necessary anymore, but I'm paranoid */
	QWidget* content_container_;
};

/* Old aliases used when the sections weren't templateized.
 *
 * These are kept to keep old code working and can largely
 * be ignored for anything new.
 *
 * SelectableSection is actually just a generic "long text" */
using LabelledSection = Section<LabelledParagraph>;
using SelectableSection = Section<Paragraph>;
using OneLineSection = Section<Paragraph>;

} // namespace TextWidgets

#endif // MINORI_GUI_WIDGETS_TEXT_H_
