#include "StoryUnitDocumentParser.h"

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

NodeStoryUnit::NodeStoryUnit(DocCore * doc, const QString & name)
    : doc_ref(doc), name_store(name)
{
}

QString NodeStoryUnit::name() const
{
    return name_store;
}

DocCore * NodeStoryUnit::document() const
{
    return doc_ref;
}

int NodeStoryUnit::typeValue() const
{
    return NODE_STORYUNIT;
}

DesNode * NodeStoryUnit::parent() const
{
    return nullptr;
}

void NodeStoryUnit::appendChild(DesNode * ins)
{
    children_nodes << ins;
}

QList<DesNode*> NodeStoryUnit::children() const
{
    return children_nodes;
}

bool NodeStoryUnit::check(QList<QString>& reasons) const
{
    return false;
}

QString NodeStoryUnit::toString() const
{
    QString  rets = "#单元 " + name_store + "{";
    for (auto it : children_nodes)
        rets += "\n" + it->toString();
    rets += "\n}";
    return rets;
}


NodeStoryFragment::NodeStoryFragment(NodeStoryUnit * unit, const QString & name)
    : unit_ins(unit), name_store(name)
{
}

DocCore * NodeStoryFragment::document() const
{
    return unit_ins->document();
}

int NodeStoryFragment::typeValue() const
{
    return NODE_STORYFRAGMENT;
}

DesNode * NodeStoryFragment::parent() const
{
    return unit_ins;
}

void NodeStoryFragment::appendChild(DesNode * ins)
{
    children_nodes << ins;
}

QList<DesNode*> NodeStoryFragment::children() const
{
    return children_nodes;
}

bool NodeStoryFragment::check(QList<QString>& reasons) const
{
    return false;
}

QString NodeStoryFragment::toString() const
{
    QString rets = QString(depth(), ' ') + "#情节 " + name() + "{";
    for (auto cin : children_nodes)
        rets += "\n" + QString(depth(), ' ') + cin->toString();
    return rets + "\n"+QString(depth(), ' ') + "}";
}

QString NodeStoryFragment::name() const
{
    return name_store;
}


NodeStoryPointRefer::NodeStoryPointRefer(DesNode * parent, const QString & chain, const QString & point)
    : parent_ins(parent), chain_name(chain), point_name(point) {}

DocCore * NodeStoryPointRefer::document() const
{
    return parent_ins->document();
}

int NodeStoryPointRefer::typeValue() const
{
    return NODE_POINTREFERENCE;
}

DesNode * NodeStoryPointRefer::parent() const
{
    return parent_ins;
}

void NodeStoryPointRefer::appendChild(DesNode * ins) {}

QList<DesNode*> NodeStoryPointRefer::children() const
{
    return QList<DesNode*>();
}

bool NodeStoryPointRefer::check(QList<QString>& reasons) const
{
    return false;
}

QString NodeStoryPointRefer::toString() const
{
    return QString("{@节点 %1 %2}").arg(chain_name).arg(point_name);
}

NodeStoryFragmentComment::NodeStoryFragmentComment(DesNode * parent,
                                                   const QString &order, const QString & name)
    : parent_ins(parent), name_store(name), order_name(order)
{
}

QString NodeStoryFragmentComment::order() const
{
    return order_name;
}

DocCore * NodeStoryFragmentComment::document() const
{
    return parent_ins->document();
}

int NodeStoryFragmentComment::typeValue() const
{
    return NODE_ORDEREDCOMMENT;
}

DesNode * NodeStoryFragmentComment::parent() const
{
    return parent_ins;
}

void NodeStoryFragmentComment::appendChild(DesNode * ins)
{
    children_nodes << ins;
}

QList<DesNode*> NodeStoryFragmentComment::children() const
{
    return children_nodes;
}

bool NodeStoryFragmentComment::check(QList<QString>& reasons) const
{
    return false;
}

QString NodeStoryFragmentComment::toString() const
{
    auto xrets = QString(depth(), ' ') + "#注解 " + name() +" "+ order() +" "+ orderValue() + "{";
    for (auto it : children_nodes)
        xrets += "\n" + QString(depth(), ' ') + it->toString();
    xrets += "\n" + QString(depth(), ' ') + "}";

    return xrets;
}

QString NodeStoryFragmentComment::name() const
{
    return name_store;
}

QString NodeStoryFragmentComment::orderValue() const
{
    return order_value;
}

void NodeStoryFragmentComment::resetValue(const QString &value)
{
    this->order_value = value;
}

NodeStoryUnitParser::NodeStoryUnitParser(ProjectCore * core)
    : XSyntaxBase("故事单元"), pjt_core(core)
{
    set_common_expression("::换行前缀", {Elm("{换行符}"),Elm("{换行符}", true)});
    auto rule = addRule("进入单元解析", 0, [this](const QList<LexResult> &seqs, int cnt)->ParseResult {
        auto nmidx = cnt - 1, defidx = cnt - 2;;

        auto node = new NodeStoryUnit(this->docRef(), seqs[nmidx].Text);
        this->refocusNode(node);

        auto word0 = new Words(node, docRef(), seqs[defidx].Text, seqs[defidx].StartRow, seqs[defidx].StartCol);
        auto word1 = new Words(node, docRef(), seqs[nmidx].Text, seqs[nmidx].StartRow, seqs[nmidx].StartCol);
        docRef()->append(word0);
        docRef()->append(word1);

        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 NodeStoryMixedDesGroupParser(this) << new NodeStoryFragmentParser(this));
}

ProjectCore * NodeStoryUnitParser::project() const
{
    return pjt_core;
}

StoryUnitDocumentParser::StoryUnitDocumentParser(ProjectCore * ins)
{
    appendTokensDefine({
                           {"{单元定义}", "#单元"},
                           {"{情节定义}", "#情节"},
                           {"{注解定义}", "#注解"},
                           {"{节点引用}", "\\{@节点"},
                           {"{描述文本}", "[^#@\\{\\}\\n]+"},
                           {"{左界限}", "\\{"},
                           {"{右界限}", "\\}"},
                           {"{换行符}", "\\n"},
                       }, "{无法识别}");

    auto chain_parser = new NodeStoryUnitParser(ins);
    appendParser(chain_parser);
}

NodeStoryFragmentParser::NodeStoryFragmentParser(NodeStoryUnitParser * pparser)
    : XSyntaxBase("故事情节"), parent_parser(pparser)
{
    set_common_expression("::换行前缀", {Elm("{换行符}"),Elm("{换行符}", true)});
    auto rule = addRule("进入情节解析", 0, [this](const QList<LexResult> &seqs, int cnt)->ParseResult {
        auto nmidx = cnt - 1, defidx = cnt - 2;;

        auto parent_parser = nodeStoryUnitParser();
        auto node = new NodeStoryFragment(static_cast<NodeStoryUnit*>(parent_parser->currNode()), seqs[nmidx].Text);
        this->refocusNode(node);
        parent_parser->currNode()->appendChild(node);

        auto word0 = new Words(node, docRef(), seqs[defidx].Text, seqs[defidx].StartRow, seqs[defidx].StartCol);
        auto word1 = new Words(node, docRef(), seqs[nmidx].Text, seqs[nmidx].StartRow, seqs[nmidx].StartCol);
        docRef()->append(word0);
        docRef()->append(word1);

        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 NodeStoryMixedDesGroupParser(this) << new NodeStoryFragmentCommentParser(this));
}

NodeStoryUnitParser * NodeStoryFragmentParser::nodeStoryUnitParser() const
{
    return parent_parser;
}

DocCore * NodeStoryFragmentParser::docRef() const
{
    return parent_parser->docRef();
}

#include "StoryChainDocumentParser.h"
NodeStoryMixedDesGroupParser::NodeStoryMixedDesGroupParser(XSyntaxBase * parent)
    : XSyntaxBase("描述块", MatchType::Outline), parent_parser(parent),
      unique_tidy(new NodeStoryLinePrefixParser (this))
{
    set_common_expression("::换行前缀", {Elm("{换行符}"),Elm("{换行符}", true)});
    set_common_expression("::基础引用定义", { Elm("{节点引用}"),Elm("{描述文本}1"), Elm("{描述文本}2"), Elm("{右界限}", true) });
    set_common_expression("::基础文本块定义", {Elm("{描述文本}"), Elm("{描述文本}", true) });

    auto rule = addRule("进入描述块解析", 0, [this](const QList<LexResult> &seqs, int cnt)->ParseResult {
		auto state = seqs[0].Token == QString("{换行符}");
        unique_tidy->setMatchEnable(state);

        auto group = new NodeStoryDesGroup(parent_parser->currNode());
        parent_parser->currNode()->appendChild(group);

        this->refocusNode(group);
        return ParseResult::EnterNext;
    });
    rule->addExpression("文本块混合定义x", { Exp("::基础引用定义", true), Exp("::基础引用定义"), Exp("::基础文本块定义", true), Exp("::基础引用定义")});
    rule->addExpression("文本块混合定义y", {Exp("::基础文本块定义", true), Exp("::基础引用定义"),Exp("::基础引用定义", true), Exp("::基础文本块定义")} );
    rule->addExpression("拓展文本块x", { Exp("::换行前缀"), Exp("文本块混合定义x", true)});
    rule->addExpression("拓展文本块y", { Exp("::换行前缀"), Exp("文本块混合定义y", true)});

    addChild(QList<SyntaxParser*>() << unique_tidy << new NodeStoryTextSpanParser(this) << new NodeStoryPointReferParser(this));
}

void NodeStoryMixedDesGroupParser::reset()
{
    XSyntaxBase::reset();
}

NodeStoryTextSpanParser::NodeStoryTextSpanParser(XSyntaxBase *parent)
    : Syntax::XSyntaxBase("文本块"), parent_parser(parent)
{
    set_common_expression("::换行前缀", {Elm("{换行符}"),Elm("{换行符}", true)});

    auto rule = addRule("解析TextSpan", 0, [this](const QList<LexResult> &seqs, int cnt)->ParseResult {
        auto pnode = parent_parser->currNode();
        for(auto idx=0; idx<cnt; ++idx){
            DesNode *node = docRef()->unknowns();
            if(seqs[idx].Token != "{换行符}"){
                node = new NodeStoryDesBlock(pnode, seqs[idx].Text);
                pnode->appendChild(node);
            }

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

        return ParseResult::Completed;
    });

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

NodeStoryPointReferParser::NodeStoryPointReferParser(XSyntaxBase *parent)
    : Syntax::XSyntaxBase("节点引用"), parent_parser(parent)
{
    set_common_expression("::换行前缀", {Elm("{换行符}"),Elm("{换行符}", true)});

    auto rule = addRule("解析节点引用", 0, [this](const QList<LexResult> &seqs, int cnt)->ParseResult {
        auto pnode = parent_parser->currNode();
        auto chain_unit = seqs[cnt-3];
        auto point_unit = seqs[cnt-2];

        auto refer = new NodeStoryPointRefer(pnode, chain_unit.Text, point_unit.Text);
        pnode->appendChild(refer);

        auto word3 = new Words(refer, docRef(), seqs[cnt-1].Text, seqs[cnt-1].StartRow, seqs[cnt-1].StartCol);
        auto word2 = new Words(refer, docRef(), point_unit.Text, point_unit.StartRow, point_unit.StartCol);
        auto word1 = new Words(refer, docRef(), chain_unit.Text, chain_unit.StartRow, chain_unit.StartCol);
        auto word0 = new Words(refer, docRef(), seqs[cnt-4].Text, seqs[cnt-4].StartRow, seqs[cnt-4].StartCol);

        docRef()->append(word3);
        docRef()->append(word2);
        docRef()->append(word1);
        docRef()->append(word0);

        return ParseResult::Completed;
    });

    rule->addExpression("基础引用定义", { Elm("{节点引用}"),Elm("{描述文本}1"), Elm("{描述文本}2"), Elm("{右界限}", true) });
//    rule->addExpression("拓展引用定义", {Exp("::换行前缀"), Exp("基础引用定义",true)});
}

/**
 * 故事情节有序注释，单独解析
 * #注解 注解名 序列名 值 {
 *      注解段落
 *      注解段落
 * }
 */
NodeStoryFragmentCommentParser::NodeStoryFragmentCommentParser(Syntax::SyntaxParser *pparser)
    : Syntax::XSyntaxBase("有序注解", MatchType::Entirely), pparser(pparser)
{
    set_common_expression("::换行前缀", {Elm("{换行符}"),Elm("{换行符}", true)});
    auto rule = this->addRule("进入注解", 0, [this](const QList<LexResult> &seqs, int cnt)->ParseResult{
        auto nmidx = cnt - 3;
        auto oridx = cnt - 2;
        auto vidx = cnt - 1;

        auto pnode = this->pparser->currNode();
        auto comment = new NodeStoryFragmentComment(pnode, seqs[oridx].Text, seqs[nmidx].Text);
        comment->resetValue(seqs[vidx].Text);
        pnode->appendChild(comment);
        refocusNode(comment);

        auto word0 = new Words(comment, docRef(), seqs[cnt-4].Text, seqs[cnt-4].StartRow, seqs[cnt-4].StartCol);
        auto word1 = new Words(comment, docRef(), seqs[nmidx].Text, seqs[nmidx].StartRow, seqs[nmidx].StartCol);
        auto word2 = new Words(comment, docRef(), seqs[oridx].Text, seqs[oridx].StartRow, seqs[oridx].StartCol);
        auto word3 = new Words(comment, docRef(), seqs[vidx].Text, seqs[vidx].StartRow, seqs[vidx].StartCol);

        docRef()->append(word0);
        docRef()->append(word1);
        docRef()->append(word2);
        docRef()->append(word3);

        return ParseResult::SelfManipulate;
    });
    rule->addExpression("基础注解定义", {Elm("{注解定义}"), Elm{"{描述文本}1"}, Elm{"{描述文本}2"}, Elm{"{描述文本}3", 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 NodeStoryMixedDesGroupParser(this));
}


NodeStoryLinePrefixParser::NodeStoryLinePrefixParser(SyntaxParser *pparent)
    : Syntax::XSyntaxBase("换行符清理", MatchType::Entirely), critical_rule(nullptr)
{
    critical_rule = addRule("清理换行符", 0, [this](const QList<LexResult> &seqs, int cnt)->ParseResult
    {
		this->setMatchEnable(false);
        return ParseResult::Completed;
    });
    critical_rule->addExpression("清理换行符x", {Elm{"{换行符}"},Elm{"{换行符}", true}});
}

void NodeStoryLinePrefixParser::setMatchEnable(bool v)
{
    critical_rule->setEnable(v);
}



