#include "StoryChainDocumentParser.h"
#include "storyconceptdocumentparser.h"

using namespace Parse;
using namespace Parse::Result;
using namespace Syntax;
using namespace Syntax::Defines;
using namespace Lex;

StoryConceptDocumentParser::StoryConceptDocumentParser(ParseCore *core)
{
    appendTokensDefine({
            {"{概念定义}","#概念"},
            {"{要点定义}", "#要点"},
            {"{描述文本}", "[^#@\\{\\}\\n]+"},
            {"{左界限}","\\{"},
            {"{右界限}","\\}"},
            {"{换行符}","\\n"}
        }, "{无法识别}");

    auto chain_parser = new NodeStoryConceptParser(core);
    appendParser(chain_parser);
}

Parse::NodeStoryConcept::NodeStoryConcept(const QString &name, DocCore *doc)
    : Result::NamedNode(name, doc, NODE_STORYCONCEPT, nullptr)
{

}

bool NodeStoryConcept::check(QList<ErrorMessage> &reasons) const
{
    auto nodes = doc()->core()->queryStoryConcept(name()[0]);
    if(nodes.size() > 1){
        ErrorMessage ins(this);
        ins.CodeRow = refered().first()->row();
        ins.CodeCol = refered().first()->column();
        ins.FilePath = doc()->filePath();
        ins.Reason = "概念重复定义";
        ins.Text = name()[0];
        reasons << ins;
    }
    return nodes.size() == 1;
}

QString NodeStoryConcept::toString() const
{
    QString string = "";
    string += "#概念 "+name()[0] + " {";
    for(auto &c : children())
        string += "\n" + QString(depth(), ' ') + c->toString();
    string +="\n" + QString(depth(),' ') + "}";

    return string;
}

NodeStoryStrongPoint::NodeStoryStrongPoint(NodeStoryConcept *parent, const QString &name)
    : Result::NamedNode(name, parent->doc(), NODE_STORYSTRONGPOINT, parent),
      concept_point(parent)
{

}

bool NodeStoryStrongPoint::check(QList<ErrorMessage> &reasons) const
{
    auto concept = parent();
    auto nodes = doc()->core()->queryStoryStrongPoint(concept, name()[0]);
    if(nodes.size() > 1){
        ErrorMessage ins(this);
        ins.CodeRow = refered().first()->row();
        ins.CodeCol = refered().first()->column();
        ins.FilePath = doc()->filePath();
        ins.Reason = "要点重复定义";
        ins.Text = name()[0];
        reasons << ins;
    }
    return nodes.size() == 1;
}

QString NodeStoryStrongPoint::toString() const
{
    QString string = "#要点 " + name()[0] + " {";
    for(auto &c : children())
        string += "\n" + QString(depth(), ' ') + c->toString();
    string += "\n" + QString(depth(),' ') + "}";
    return string;
}

QList<QString> NodeStoryStrongPoint::name() const
{
    QList<QString> rets;
    rets << NamedNode::name()[0] << concept_point->name()[0];
    return rets;
}

NodeStoryConceptParser::NodeStoryConceptParser(Result::ParseCore *core)
    : Syntax::XSyntaxBase("概念解析"), core(core)
{
    set_common_expression("::换行前缀", {Elm("{换行符}"), Elm("{换行符}", true)});

    auto rule = addRule("进入概念解析", 0, [this](const QList<LexResult> &seqs, int cnt)->ParseResult
    {
        auto nmunit = seqs[cnt-1];
        auto defunit = seqs[cnt-2];
        auto node = new NodeStoryConcept(nmunit.Text, docRef());
        refocusNode(node);

        auto word1 = new Words(node, docRef(), defunit.Text, defunit.StartRow, defunit.StartCol);
        auto word0 = new Words(node, docRef(), nmunit.Text, nmunit.StartRow, nmunit.StartCol);
        docRef()->append(word1);
        docRef()->append(word0);

        return ParseResult::SelfManipulate;
    });
    rule->addExpression("基础概念定义", {Elm("{概念定义}"), Elm("{描述文本}", true)});
    rule->addExpression("拓展概念定义", {Exp("::换行前缀"), Exp("基础概念定义", true)});

    rule = addRule("进入成分解析", 1, [this](const QList<LexResult> &seqs, int cnt)->ParseResult {
        auto node = currNode();

        auto word = new Words(node, docRef(), seqs[cnt - 1].Text, seqs[cnt - 1].StartRow, seqs[cnt - 1].StartCol);
        docRef()->append(word);

        return ParseResult::EnterNext;
    });
    rule->addExpression("基础成分解析", { Elm("{左界限}", true) });
    rule->addExpression("拓展成分解析", { Exp("::换行前缀"), Exp("基础成分解析", true) });

    rule = addRule("跳出成分解析", 2, [this](const QList<LexResult> &seqs, int cnt)->ParseResult {
        auto node = currNode();

        auto word = new Words(node, docRef(), seqs[cnt - 1].Text, seqs[cnt - 1].StartRow, seqs[cnt - 1].StartCol);
        docRef()->append(word);

        return ParseResult::Completed;
    });
    rule->addExpression("基础跳出解析", { Elm("{右界限}", true) });
    rule->addExpression("拓展跳出解析", { Exp("::换行前缀"), Exp("基础跳出解析", true) });

    addChild(QList<SyntaxParser*>() << new NodeStoryPureTextDesGroupParser(this)
             << new NodeStoryStrongPointParser(this));
}




NodeStoryStrongPointParser::NodeStoryStrongPointParser(NodeStoryConceptParser *pparser)
    : Syntax::XSyntaxBase("要点解析")
{
    set_common_expression("::换行前缀", {Elm("{换行符}"), Elm("{换行符}", true)});

    auto rule = addRule("进入要点解析", 0, [this, pparser](const QList<LexResult> &seqs, int cnt)->ParseResult
    {
        auto nmunit = seqs[cnt-1];
        auto defunit = seqs[cnt-2];
        auto node = new NodeStoryStrongPoint(static_cast<NodeStoryConcept*>(pparser->currNode()), nmunit.Text);
        refocusNode(node);
        pparser->currNode()->appendChild(node);

        auto word1 = new Words(node, docRef(), defunit.Text, defunit.StartRow, defunit.StartCol);
        auto word0 = new Words(node, docRef(), nmunit.Text, nmunit.StartRow, nmunit.StartCol);
        docRef()->append(word1);
        docRef()->append(word0);

        return ParseResult::SelfManipulate;
    });
    rule->addExpression("基础要点定义", {Elm("{要点定义}"), Elm("{描述文本}", true)});
    rule->addExpression("拓展要点定义", {Exp("::换行前缀"), Exp("基础要点定义", true)});

    rule = addRule("进入成分解析", 1, [this](const QList<LexResult> &seqs, int cnt)->ParseResult {
        auto node = currNode();

        auto word = new Words(node, docRef(), seqs[cnt - 1].Text, seqs[cnt - 1].StartRow, seqs[cnt - 1].StartCol);
        docRef()->append(word);

        return ParseResult::EnterNext;
    });
    rule->addExpression("基础成分解析", { Elm("{左界限}", true) });
    rule->addExpression("拓展成分解析", { Exp("::换行前缀"), Exp("基础成分解析", true) });

    rule = addRule("跳出成分解析", 2, [this](const QList<LexResult> &seqs, int cnt)->ParseResult {
        auto node = currNode();

        auto word = new Words(node, docRef(), seqs[cnt - 1].Text, seqs[cnt - 1].StartRow, seqs[cnt - 1].StartCol);
        docRef()->append(word);

        return ParseResult::Completed;
    });
    rule->addExpression("基础跳出解析", { Elm("{右界限}", true) });
    rule->addExpression("拓展跳出解析", { Exp("::换行前缀"), Exp("基础跳出解析", true) });

    addChild(QList<SyntaxParser*>() << new NodeStoryPureTextDesGroupParser(this));
}





















