#include "form.h"
#include "ui_form.h"
#include <QFileDialog>
#include <QDebug>
#include "cdutils_k.h"
#include "cdutils_core.h"
#include "qcd_core.h"
#include "qcd_kmodel.h"
#include "pifile.h"


using namespace CDUtils;

PIStringList takeMembers(PIString &in) {
	int slen = in.length();
	int st = -1, bcnt = 0;
	PIChar cc;
	PIStringList ret;
	int rst = -1;
	for (int i = 0; i < slen; i++) {
		cc = in.at(i);
		if (cc == '{') {
			if (bcnt == 0) st = i;
			bcnt++;
		}
		if (cc == '}' && st >= 0) {
			bcnt--;
			if (bcnt == 0) {
				in.remove(st, i-st);
				return ret;
			}
		}
		if (cc == ';' && bcnt == 1) {
			if (rst < 0) rst = st;
			ret << in.mid(rst+1, i-rst-1);
			rst = i;
		}
	}
	return ret;
}


void parseStruct(PIString &in, CDSection * root, const PIStringList &c_types, PIVector<CDSection> &sections, PIVector<CDType> &enums);


void parseEnum(PIString &in, CDSection * root, const PIStringList &c_types, PIVector<CDSection> &sections, PIVector<CDType> &enums) {
	PIString n = in.takeCWord();
	//piCout << n;
	PIVariantTypes::Enum e;
	e.enum_name = n;
	PIString ev = in.inBrackets('{', '}');
	e << ev.split(",");
	if (root) {
		CDType & cdt((*root)[root->count(false)]);
		cdt = CDType(cdt.index(), n, "e", "", "", "", CDType::cdK);
		cdt.setEnumValues(e);
		enums << cdt;
	} else {
		enums << CDType(0, n, "e", "", "", "", CDType::cdK);
		enums.back().setEnumValues(e);
	}
	in.removeAll("{"+in+"}");
}


void parseMember(PIString &in, CDSection * root, const PIStringList &c_types, PIVector<CDSection> &sections, PIVector<CDType> &enums) {
	PIString t = in.takeCWord();
	if (t == "struct") {
		parseStruct(in, root, c_types, sections, enums);
	}
	if (t == "enum") {
		parseEnum(in, root, c_types, sections, enums);
	}
	if (root) {
		if (c_types.contains(t) && root) {
			PIString tt = "s";
			if (t == "bool") tt = "b";
			if (t == "int") tt = "n";
			if (t == "double") tt = "f";
			CDType & cdt((*root)[root->count(false)]);
			cdt = CDType(cdt.index(), in.takeCWord(), tt, "", "", "", CDType::cdK);
		}
		piForeach(CDSection cd, sections) {
			if (t == cd.name) {
				cd.alias = in.takeCWord();
				root->section(root->sectionsCount()) = cd;
			}
		}
		piForeach(CDType en, enums) {
			if (t == en.name()) {
				in.takeCWord();
				(*root)[root->count(false)] = en;
			}
		}
	}
}

void parseStruct(PIString &in, CDSection * root, const PIStringList &c_types, PIVector<CDSection> &sections, PIVector<CDType> &enums) {
	PIString t = in.takeCWord();
	CDSection * c;
	if (root) c = &(root->section(root->sectionsCount()));
	else c = new CDSection();
	c->name = t;
	c->alias = t;
	PIStringList members = takeMembers(in);
	//piCout << members;
	piForeach(PIString &s, members) {
		if (s.trim().isEmpty()) continue;
		parseMember(s, c, c_types, sections, enums);
	}
	sections << *c;
}


Form::Form(QWidget *parent) : QWidget(parent), ui(new Ui::Form) {
	CDCore::instance()->initPult();
	ui->setupUi(this);
	ui->treeView->setKFile("");

	PIFile f;
	piCout << f.open("test.kh", PIIODevice::ReadOnly);
	PIStringList c_types;
	c_types << "bool" << "int" << "double" << "string" << "PIString";
	PIString in;
	while (!f.isEnd()) {
		PIStringList s = f.readLine().trim().split("//");
		if (!s.isEmpty())
			in += s[0];
	}
	PIVector<CDSection> sections;
	PIVector<CDType> enums;
	int i=0;
	while (!in.isEmpty() && i<100) {
		if (!in[0].isAlpha()) in.takeSymbol();
		parseMember(in, 0, c_types, sections, enums);
		i++;
	}
	piForeach(CDSection cd, sections) {
		if (cd.name == "K") K.root() = cd;
	}

	ui->treeView->refresh();
}


Form::~Form() {
	delete ui;
}


void Form::on_pushButton_3_clicked() {
	ui->treeView->setKFile(QFileDialog::getSaveFileName(this, "Save"));
	ui->treeView->saveK();
	ui->treeView->setKFile("");
}


void Form::on_pushButton_4_clicked() {
	ui->treeView->setKFile(QFileDialog::getOpenFileName(this, "Open"));
	ui->treeView->loadK();
	ui->treeView->setKFile("");
	qDebug() << QCDCore::instance()->bindWindow(this);
	QCDCore::instance()->bindWidget(ui->spinRadar_Antenna_SwitchRate, K["NVA.NVA_FrameStitch"]);
}


void Form::on_pushButton_6_clicked() {
	QString fn = QFileDialog::getOpenFileName(this, trUtf8("Select *.h file with K description"), "k_description.h", "C/C++ header files(*.h *.hpp);;All files(*)");
	if (fn.isEmpty()) return;
	if (mode_dlg.exec() == QDialog::Rejected) return;
	ui->treeView->buildFromHeader(fn, mode_dlg.mode());
	/*piCout << K.root()["Radar_WaveFreqTune"];
	piCout << K.root()["11.NVA_PulseGenFineTune"];
	piCout << K.root()[".NVA.NVA_PulseGenFineTune"];
	piCout << K.root()["NVA_A.1.NVA_Clk"];*/
}


void Form::on_buttonCalc_clicked() {
	ui->treeView->calculateK();
	ui->treeView->refresh();
}
