#include "StoryBoardDocumentParser.h"
#include "StoryChainDocumentParser.h"
#include "StoryOutlineDocumentParser.h"
#include "StoryTool.h"
#include "storyconceptdocumentparser.h"

#include <StoryUnitDocumentParser.h>

using namespace MakeTools;
using namespace Parse;
using namespace Parse::Result;
using namespace CheckTools;

StoryTool::StoryTool()
    : parse_core(new ParseCore()), fragment_check(new FragmentsCheck(parse_core)){}

QList<QString> StoryTool::compile(const QFileInfo &file, const QString &doc_name)
{
    DocCore *doc_core = parse_core->queryDocument(file.absoluteFilePath());
    if(doc_core)
        doc_core->clear();

    QList<DesNode*> results;
    if(file.suffix() == "storychain"){
        if(!doc_core)
            doc_core = new DocCore(parse_core, DocType::STORYCHAIN, file.absoluteFilePath(), doc_name);

        StoryChainDocumentParser parser(parse_core);
        results.append(parser.analysis(doc_core, file.absoluteFilePath()));
    }
    else if(file.suffix() == "storyunit"){
        if(!doc_core)
            doc_core = new DocCore(parse_core, DocType::STORYUNIT, file.absoluteFilePath(), doc_name);

        StoryUnitDocumentParser parser(parse_core);
        results.append(parser.analysis(doc_core, file.absoluteFilePath()));
    }
    else if(file.suffix() == "storyboard"){
        if(!doc_core)
            doc_core = new DocCore(parse_core, DocType::STORYBOARD, file.absoluteFilePath(), doc_name);

        StoryBoardDocumentParser parser(parse_core);
        results.append(parser.analysis(doc_core, file.absoluteFilePath()));
    }
    else if(file.suffix() == "storyvolume"){
        if(!doc_core)
            doc_core = new DocCore(parse_core, DocType::STORYOUTLINES, file.absoluteFilePath(), doc_name);

        StoryOutlineDocumentParser parser(parse_core);
        results.append(parser.analysis(doc_core, file.absoluteFilePath()));
    }
    else if(file.suffix() == "storyconcept"){
        if(!doc_core)
            doc_core = new DocCore(parse_core, DocType::STORYCONCEPTS, file.absoluteFilePath(), doc_name);
        StoryConceptDocumentParser parser(parse_core);
        results.append(parser.analysis(doc_core, file.absoluteFilePath()));
    }

    if(doc_core){
        parse_core->registerDoc(doc_core);
        for(auto n : results)
            doc_core->append(n);
    }
    return QList<QString>();
}

QList<QString> StoryTool::compileSource(const QFileInfo &_file, const QString &src, const QString &doc_name)
{
    DocCore *doc_core = parse_core->queryDocument(_file.absoluteFilePath());
    if(doc_core)
        doc_core->clear();

    QList<DesNode*> results;
    if(_file.suffix() == "storychain"){
        if(!doc_core)
            doc_core = new DocCore(parse_core, DocType::STORYCHAIN, _file.absoluteFilePath(), doc_name);

        StoryChainDocumentParser parser(parse_core);
        results.append(parser.analysisSource(doc_core, src));
    }
    else if(_file.suffix() == "storyunit"){
        if(!doc_core)
            doc_core = new DocCore(parse_core, DocType::STORYUNIT, _file.absoluteFilePath(), doc_name);

        StoryUnitDocumentParser parser(parse_core);
        results.append(parser.analysisSource(doc_core, src));
    }
    else if(_file.suffix() == "storyboard"){
        if(!doc_core)
            doc_core = new DocCore(parse_core, DocType::STORYBOARD, _file.absoluteFilePath(), doc_name);

        StoryBoardDocumentParser parser(parse_core);
        results.append(parser.analysisSource(doc_core, src));
    }
    else if(_file.suffix() == "storyvolume"){
        if(!doc_core)
            doc_core = new DocCore(parse_core, DocType::STORYOUTLINES, _file.absoluteFilePath(), doc_name);

        StoryOutlineDocumentParser parser(parse_core);
        results.append(parser.analysisSource(doc_core, src));
    }
    else if(_file.suffix() == "storyconcept"){
        if(!doc_core)
            doc_core = new DocCore(parse_core, DocType::STORYCONCEPTS, _file.absoluteFilePath(), doc_name);
        StoryConceptDocumentParser parser(parse_core);
        results.append(parser.analysisSource(doc_core, src));
    }

    if(doc_core){
        parse_core->registerDoc(doc_core);
        for(auto n : results)
            doc_core->append(n);
    }
    return QList<QString>();
}

bool StoryTool::checkPass(QList<ErrorMessage> &errors)
{
    auto docs = this->parse_core->allDocuments();
    for(auto &d : docs){
        for(auto &w : d->unknowns()->refered()){
            ErrorMessage error(w->host());
            error.Reason = "无法识别内容";
            error.Text = w->toString();
            error.FilePath = d->filePath();
            error.CodeRow = w->row();
            error.CodeCol = w->column();

            errors << error;
        }

        for(auto &n : d->syntaxNodes())
            error_check(n, errors);
    }
    fragment_check->check(errors);
    return errors.size() == 0;
}

ParseCore *StoryTool::getCore() const
{
    return parse_core;
}

bool StoryTool::error_check(Parse::Result::DesNode * node, QList<ErrorMessage> &err_out)
{
    node->check(err_out);
    for(auto &n : node->children()){
        error_check(n, err_out);
    }

    return err_out.size() == 0;
}
