/*
 * Xml to Sql converter
 * Author: https://ryo.nopwd.lol
 * Version: alpha
 */

#include <libxml/parser.h>
#include <libxml/tree.h>
#include <stdio.h>
#include <string.h>

#define astrtr(s) s[strlen(s)-1] = '\0'
#define astrcmp(s1, s2) xmlStrcmp(s1, (xmlChar *)s2) == 0
#define asprintf(dst, ...) sprintf(dst+strlen(dst), __VA_ARGS__)

void query_create(xmlNode *root, char query[]);
void query_insert(xmlNode *root, char query[]);

int main(int argc, char *argv[])
{
	xmlDocPtr doc;
	xmlNodePtr root;
	char query[2048] = { '\0' };

	if (argc < 2) {
		fprintf(stderr, "no input file\n");
		return 1;
	}

	doc = xmlReadFile(argv[1], NULL, XML_PARSE_NOBLANKS);
	if (doc == NULL) {
		fprintf(stderr, "can not parse the document\n");
		return 1;
	}

	root = xmlDocGetRootElement(doc);

	query_create(root, query);
	query_insert(root, query);
	puts(query);

	xmlFreeDoc(doc);
	return 0;
}

void query_create(xmlNode *root, char query[])
{
	xmlNode *cur, *parent;
	int uuid = 0, end, nested = 0;

	cur = root;
	while (cur) {
		asprintf(query, "CREATE TABLE %s(", cur->name);
		cur = cur->children;
		if (cur->children->type == XML_ELEMENT_NODE) {
			parent = cur->parent;
			nested = 1;
			cur = cur->children;
		}

		while (cur->children->type == XML_TEXT_NODE) {
			if (astrcmp(cur->name, "uuid"))
				uuid = 1;

			asprintf(query, "%s,", cur->name);

			cur = cur->next;
			if (cur == NULL) break;
		}
		if (nested) {
			cur = parent->next;
			nested = 0;
		}

		if (!uuid) {
			asprintf(query, "%s_uuid,", root->name);
		}

		astrtr(query);
		strcat(query, ");\n");
	}
}

void query_insert(xmlNode *root, char query[])
{
	xmlNode *cur, *parent;
	int uuid = 0, end, nested = 0;

	cur = root;
	while (cur) {
		asprintf(query, "INSERT INTO %s VALUES(", cur->name);
		cur = cur->children;
		if (cur->children->type == XML_ELEMENT_NODE) {
			parent = cur->parent;
			nested = 1;
			cur = cur->children;
		}

		while (cur->children->type == XML_TEXT_NODE) {
			if (astrcmp(cur->name, "uuid"))
				uuid = 1;

			asprintf(query, "'%s',", xmlNodeGetContent(cur));

			if (cur->next == NULL) {
				if (nested) {
					if (cur->parent == parent->last) {
						break;
					}
					else {
						astrtr(query);
						strcat(query, "),\n(");
						cur = cur->parent->next->children;
					}
				} else {
					cur = cur->next;
					break;
				}
			} else
				cur = cur->next;
		}

		if (nested) {
			cur = parent->next;
			nested = 0;
		}

		if (!uuid) {
			asprintf(query, "'%s',", xmlNodeGetContent(root->children));
		}

		astrtr(query);
		strcat(query, ");\n");
	}
	astrtr(query);
}

