#include "gui/widgets/text.h"
#include "core/session.h"

#include <QDebug>
#include <QFrame>
#include <QLabel>
#include <QTextBlock>
#include <QVBoxLayout>
#include <QScrollArea>
#include <QDebug>

/* WARNING: GARBAGE CODE FOLLOWS
 *
 * This file is filled with spaghetti to make this
 * stupid text render how I want it to.
 *
 * many cases of hacking with setSizePolicy() are seen
 * all around this file. Edit it only if really
 * necessary, please.
*/

namespace TextWidgets {

Header::Header(const QString& title, QWidget* parent)
	: QWidget(parent)
	, static_text_title(title) {
	QVBoxLayout* layout = new QVBoxLayout(this);
	setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);

	static_text_title.setTextFormat(Qt::PlainText);

	{
		QFont font = static_text_title.font();
		font.setWeight(QFont::Bold);
		static_text_title.setFont(font);
	}

	static_text_line.setFrameShape(QFrame::HLine);
	static_text_line.setFrameShadow(QFrame::Sunken);
	static_text_line.setFixedHeight(2);

	layout->addWidget(&static_text_title);
	layout->addWidget(&static_text_line);
	layout->setSpacing(0);
	layout->setContentsMargins(0, 0, 0, 0);
}

void Header::SetText(const QString& text) {
	static_text_title.setText(text);
	updateGeometry();
}

Paragraph::Paragraph(const QString& text, QWidget* parent) : QWidget(parent) {
	/* meh */
	setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);

	QVBoxLayout* layout = new QVBoxLayout(this);
	layout->setSpacing(0);
	layout->setContentsMargins(0, 0, 0, 0);

	text_edit.setTextInteractionFlags(Qt::TextBrowserInteraction);
	text_edit.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
	text_edit.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
	text_edit.setStyleSheet("background: transparent;");
	text_edit.setFrameStyle(QFrame::NoFrame);

	text_edit.document()->setDocumentMargin(0);

	SetText(text);

	layout->addWidget(&text_edit);
}

void Paragraph::SetText(const QString& text) {
	text_edit.document()->setPlainText(text);

	/* return the view to the start */
	QTextCursor cursor = text_edit.textCursor();
	cursor.setPosition(0);
	text_edit.setTextCursor(cursor);
}

bool Paragraph::hasHeightForWidth() const {
	return true;
}

int Paragraph::heightForWidth(int w) const {
	QTextDocument* doc = text_edit.document();
	doc->setTextWidth(w);

	return doc->size().toSize().height();
}

QPlainTextEdit* Paragraph::GetLabel() {
	return &text_edit;
}

Line::Line(QWidget* parent) : QWidget(parent) {
	QVBoxLayout* layout = new QVBoxLayout(this);
	layout->setSpacing(0);
	layout->setContentsMargins(0, 0, 0, 0);

	line_edit_.setReadOnly(true);
	line_edit_.setFrame(false);
	line_edit_.setStyleSheet("background: transparent;");

	layout->addWidget(&line_edit_);
}

Line::Line(const QString& text, QWidget* parent) : Line(parent) {
	SetText(text);
}

void Line::SetText(const QString& text) {
	line_edit_.setText(text);
	line_edit_.setCursorPosition(0);
}

Title::Title(const QString& title, QWidget* parent) : Line(title, parent) {
	QFont fnt(line_edit_.font());
	fnt.setPixelSize(16);
	line_edit_.setFont(fnt);

	line_edit_.setForegroundRole(QPalette::Highlight);
}

Section::Section(const QString& title, const QString& data, QWidget* parent)
	: QWidget(parent) {
	QVBoxLayout* layout = new QVBoxLayout(this);

	header = new Header(title, this);

	QWidget* content = new QWidget(this);
	QHBoxLayout* content_layout = new QHBoxLayout(content);

	paragraph = new Paragraph(data, this);
	paragraph->GetLabel()->setTextInteractionFlags(Qt::NoTextInteraction);
	paragraph->GetLabel()->setAttribute(Qt::WidgetAttribute::WA_TransparentForMouseEvents);
	paragraph->GetLabel()->setWordWrapMode(QTextOption::NoWrap);

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

	layout->addWidget(header);
	layout->addWidget(paragraph);
	layout->setSpacing(0);
	layout->setContentsMargins(0, 0, 0, 0);
}

Header* Section::GetHeader() {
	return header;
}

Paragraph* Section::GetParagraph() {
	return paragraph;
}

/* despite being named a "labelled paragraph" this uses QLabels for simplicity */
LabelledParagraph::LabelledParagraph(const QString& label, const QString& data, QWidget* parent)
	: QWidget(parent)
	, labels_(label)
	, data_(data) {
	QHBoxLayout* ly = new QHBoxLayout(this);

	labels_.setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
	data_.setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);

	ly->addWidget(&labels_, 0, Qt::AlignTop);
	ly->addWidget(&data_, 0, Qt::AlignTop);
	ly->setSpacing(20);
	ly->setContentsMargins(0, 0, 0, 0);
}

QLabel* LabelledParagraph::GetLabels() {
	return &labels_;
}

QLabel* LabelledParagraph::GetData() {
	return &data_;
}

QLabel* LabelledParagraph::GetParagraph() {
	return GetData();
}

LabelledSection::LabelledSection(const QString& title, const QString& label, const QString& data, QWidget* parent)
    : QWidget(parent) {
	QVBoxLayout* layout = new QVBoxLayout(this);

	header = new Header(title, this);

	// this is not accessible from the object because there's really
	// no reason to make it accessible...
	content = new LabelledParagraph(label, data, this);
	content->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
	content->setContentsMargins(12, 0, 0, 0);

	layout->addWidget(header);
	layout->addWidget(content);
	layout->setSpacing(0);
	layout->setContentsMargins(0, 0, 0, 0);
}

Header* LabelledSection::GetHeader() {
	return header;
}

QLabel* LabelledSection::GetLabels() {
	return content->GetLabels();
}

QLabel* LabelledSection::GetData() {
	return content->GetData();
}

QLabel* LabelledSection::GetParagraph() {
	return content->GetParagraph();
}

SelectableSection::SelectableSection(const QString& title, const QString& data, QWidget* parent) : QWidget(parent) {
	QVBoxLayout* layout = new QVBoxLayout(this);

	header = new Header(title, this);

	QWidget* content = new QWidget(this);
	QHBoxLayout* content_layout = new QHBoxLayout(content);

	paragraph = new Paragraph(data, content);

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

	layout->addWidget(header);
	layout->addWidget(content);
	layout->setSpacing(0);
	layout->setContentsMargins(0, 0, 0, 0);
}

Header* SelectableSection::GetHeader() {
	return header;
}

Paragraph* SelectableSection::GetParagraph() {
	return paragraph;
}

OneLineSection::OneLineSection(const QString& title, const QString& text, QWidget* parent) : QWidget(parent) {
	QVBoxLayout* layout = new QVBoxLayout(this);

	header = new Header(title, this);

	QWidget* content = new QWidget(this);
	QHBoxLayout* content_layout = new QHBoxLayout(content);

	line = new Line(text, content);

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

	layout->addWidget(header);
	layout->addWidget(content);
	layout->setSpacing(0);
	layout->setContentsMargins(0, 0, 0, 0);
}

Header* OneLineSection::GetHeader() {
	return header;
}

Line* OneLineSection::GetLine() {
	return line;
}

} // namespace TextWidgets
