#include "XMLConverter.h"
#include <QDebug>
#include <QStringList>
#include <QFileInfo>
#include <QFile>
#include <iostream>

void XmlConverter::parseDirectory(QDir directory)
{
    QDomDocument doc;
    QDomElement root = doc.createElement("spells");
    directory.setNameFilters(QStringList() << "*.xml");
    foreach(QFileInfo file, directory.entryInfoList())
    {
        std::cout << "Reading " << file.fileName().toStdString() << "..." << std::flush;
        XmlConverter::parseXml(file.absoluteFilePath(), root, doc);
        std::cout << std::endl;
    }
    doc.appendChild(root);

    QFile file("spells.xml");
    file.open(QIODevice::WriteOnly);
    file.write(doc.toByteArray(4));
}

void XmlConverter::parseXml(QString fileName, QDomElement &root, QDomDocument &doc)
{
    // Open document.
    QFile file(fileName);
    file.open(QIODevice::ReadOnly);
    QDomDocument sourceDoc;
    sourceDoc.setContent(&file);

    // Find spells tag.
    QDomElement spells = sourceDoc.elementsByTagName("spelldata").at(0).firstChildElement();
    while(!spells.isNull())
    {
        // Create spell tag
        QDomElement spell = doc.createElement("spell");

        // Name
        if(spells.elementsByTagName("name").size() > 0)
        {
            spell.setAttribute("name", spells.elementsByTagName("name").at(0).toElement().text());
        }
        else
        {
            spell.setAttribute("invalid", "true");
        }

        // School
        if(spells.elementsByTagName("school").size() > 0)
        {
            spell.setAttribute("school", spells.elementsByTagName("school").at(0).toElement().text());
        }
        else
        {
            spell.setAttribute("invalid", "true");
        }

        // Level
        if(spells.elementsByTagName("level").size() > 0)
        {
            spell.setAttribute("level", spells.elementsByTagName("level").at(0).toElement().text());
        }
        else
        {
            spell.setAttribute("invalid", "true");
        }

        // Concentration
        if(spells.elementsByTagName("duration").size() > 0)
        {
            spell.setAttribute("concentration", spells.elementsByTagName("duration").at(0).toElement().text().toLower().contains("concentration") ? "true" : "false");
        }
        else
        {
            spell.setAttribute("invalid", "true");
        }

        // Ritual
        if(spells.elementsByTagName("ritual").size() > 0 && spells.elementsByTagName("ritual").at(0).toElement().text() == "1")
        {
            spell.setAttribute("ritual", "true");
        }
        else
        {
            spell.setAttribute("ritual", "false");
        }

        // Casting classes
        QDomElement classes = doc.createElement("classes");
        if(spells.elementsByTagName("source").size() > 0)
        {
            foreach(QString caster, spells.elementsByTagName("source").at(0).toElement().text().split(","))
            {
                QDomElement castingClass = doc.createElement("class");
                castingClass.appendChild(doc.createTextNode(caster.simplified()));
                classes.appendChild(castingClass);
            }
        }
        else
        {
            spell.setAttribute("invalid", "true");
        }
        spell.appendChild(classes);

        // Description
        QDomElement description = doc.createElement("description");
        if(spells.elementsByTagName("description").size() > 0)
        {
            QString desc;
            QTextStream stream(&desc);
            spells.elementsByTagName("description").at(0).toElement().save(stream, 4);
            desc.replace("<description type=\"formattedtext\">", "");
            desc.replace("</description>", "");
            description.appendChild(doc.createCDATASection(desc.simplified()));
        }
        else
        {
            spell.setAttribute("invalid", "true");
        }
        spell.appendChild(description);

        // Castingtime
        QDomElement castingtime = doc.createElement("castingtime");
        if(spells.elementsByTagName("castingtime").size() > 0)
        {
            castingtime.appendChild(doc.createTextNode(spells.elementsByTagName("castingtime").at(0).toElement().text()));
        }
        else
        {
            spell.setAttribute("invalid", "true");
        }
        spell.appendChild(castingtime);

        // Range
        QDomElement range = doc.createElement("range");
        if(spells.elementsByTagName("range").size() > 0)
        {
            range.appendChild(doc.createTextNode(spells.elementsByTagName("range").at(0).toElement().text()));
        }
        else
        {
            spell.setAttribute("invalid", "true");
        }
        spell.appendChild(range);

        // Duration
        QDomElement duration = doc.createElement("duration");
        if(spells.elementsByTagName("duration").size() > 0)
        {
            duration.appendChild(doc.createTextNode(spells.elementsByTagName("duration").at(0).toElement().text()));
        }
        else
        {
            spell.setAttribute("invalid", "true");
        }
        spell.appendChild(duration);

        // Components
        QDomElement components = doc.createElement("components");
        if(spells.elementsByTagName("components").size() > 0)
        {
            components.setAttribute("humanreadable", spells.elementsByTagName("components").at(0).toElement().text());

            QStringList splitComponents = spells.elementsByTagName("components").at(0).toElement().text().split("(");
            QStringList componentString;
            QString materialsString = "";
            if(splitComponents.size() > 1)
            {
                componentString = splitComponents.at(0).split(",");
                splitComponents.removeAt(0);
                materialsString = "(" + splitComponents.join("(");
            }
            else
            {
                componentString = splitComponents.at(0).split(",");
            }

            for(int i = 0; i < componentString.size(); ++i)
            {
                componentString[i] = componentString[i].simplified().toLower();
            }

            QDomElement vocal = doc.createElement("vocal");
            vocal.appendChild(doc.createTextNode(componentString.contains("v") ? "true" : "false"));
            components.appendChild(vocal);

            QDomElement somatic = doc.createElement("somatic");
            somatic.appendChild(doc.createTextNode(componentString.contains("s") ? "true" : "false"));
            components.appendChild(somatic);

            QDomElement material = doc.createElement("material");
            if(!materialsString.isEmpty())
            {
                materialsString.remove(0, 1);
                materialsString.chop(1);
                material.setAttribute("name", materialsString);
                material.setAttribute("expensive", materialsString.toLower().contains(" gp") ? "true" : "false");
                material.setAttribute("consumed", materialsString.toLower().contains(" gp") && (materialsString.toLower().contains("consumed") ||materialsString.toLower().contains("consumes")) ? "true" : "false");
                material.appendChild(doc.createTextNode("true"));
            }
            else
            {
                material.appendChild(doc.createTextNode("false"));
            }
            components.appendChild(material);
        }
        else
        {
            spell.setAttribute("invalid", "true");
        }
        spell.appendChild(components);

        if(!spell.hasAttribute("invalid"))
        {
            root.appendChild(spell);
        }
        else
        {
            std::cerr << "INVALID SPELL FOUND!" << std::endl;
        }
        std::cout << "." << std::flush;
        spells = spells.nextSiblingElement();
    }
}
