#include "storyboardspresent.h"
#include "command_list.h"
#include "opstream.h"

#include <QSplitter>
#include <QVBoxLayout>

using namespace Components;
using namespace Parse::Result;
using namespace DataModel;

StoryboardsPresent::StoryboardsPresent(Schedule::CommandsDispatcher *core, StoryboardsPresentModel *backend, QWidget *parent)
    : QWidget(parent), core_ins(core), tree_view(new QTreeView(this)), details_view(new QTextEdit(this)) {
    tree_view->setModel(backend->treeModel());
    details_view->setDocument(backend->detailBackend());
    details_view->setReadOnly(true);

    auto layout = new QVBoxLayout(this);
    layout->setMargin(0);
    auto splitter= new QSplitter(Qt::Vertical, this);
    layout->addWidget(splitter);
    splitter->addWidget(tree_view);
    splitter->addWidget(details_view);

    connect(tree_view,  &QTreeView::expanded,  [this](){
        tree_view->resizeColumnToContents(0);
        tree_view->resizeColumnToContents(1);
    });

    connect(tree_view, &QTreeView::clicked, this,  &StoryboardsPresent::show_current_details);
}

using namespace CommandList;
void StoryboardsPresent::show_current_details(const QModelIndex &idx) {
    if (!idx.isValid())
        return;

    QList<QString> path;
    auto node = idx;
    while (true) {
        auto name = node.data().toString();
        if (name.isEmpty())
            break;
        path.insert(0, name);
        node = node.parent();
    }
    core_ins->postCommand(StoryboardDetailShow(path));
}

void StoryboardsPresent::jump_to(const QModelIndex &idx) {
    if (!idx.isValid())
        return;

    QList<QString> path;
    auto node = idx;
    while (true) {
        auto name = node.data().toString();
        if (name.isEmpty())
            break;
        path.insert(0, name);
        node = node.parent();
    }
    core_ins->postCommand(StoryboardJumpTo(path));
}

QString StoryboardsPresent::name() const { return NAME(StoryboardsPresent); }

QWidget *StoryboardsPresent::widget() const { return (QWidget *)this; }

DataModel::StoryboardsPresentModel::StoryboardsPresentModel(Core::AppCore *core)
    : core_ins(core), model_base(new QStandardItemModel),
      detail_backend(new QTextDocument) {}

StoryboardsPresentModel::~StoryboardsPresentModel() {
    delete model_base;
    delete detail_backend;
}

void DataModel::StoryboardsPresentModel::refresh() {
    model_base->clear();
    model_base->setHorizontalHeaderLabels(QStringList() << "名称"
                                                        << "单元");
    auto storys = core_ins->parseCore()->allStoryBoards();

    for (auto &b : storys) {
        auto item = new QStandardItem(static_cast<NamedNode *>(b)->name()[0]);
        item->setEditable(false);
        model_base->appendRow(item);

        auto refers = b->children();
        for (auto &ref : refers) {
            if (ref->typeValue() != NODE_FRAGMENTREFERENCE)
                continue;

            QList<QStandardItem *> row;
            row << new QStandardItem("@" +
                                     static_cast<NamedNode *>(ref)->name()[0]);
            row.last()->setEditable(false);
            row << new QStandardItem(static_cast<NamedNode *>(ref)->name()[1]);
            row.last()->setEditable(false);

            item->appendRow(row);
        }
    }
}

using namespace Operate;
void DataModel::StoryboardsPresentModel::detailShow(
    const QList<QString> &navi) {
    QStandardItem *item = nullptr;
    // 迭代路径获取故事链节点
    for (auto &it : navi) {
        auto result = OpStream<QStandardItem *>([this, &item](int &cnt, int idx) -> QStandardItem * {
                          if (!item) {
                              cnt = model_base->rowCount();
                              if (cnt <= 0)
                                  return nullptr;
                              return model_base->item(idx);
                          } else {
                              cnt = item->rowCount();
                              if (cnt <= 0)
                                  return nullptr;
                              return item->child(idx);
                          }
                      }).filter([it](QStandardItem *const &xit) {
                            return it == xit->text();
                        }).toList();

        if (!result.size()) {
            throw new SimpleException("指定的Storychain路径无效：" + navi.join("/"));
        } else {
            item = result.at(0);
        }
    }

    QString contents;
    if (item->parent() == nullptr) {
        auto node = core_ins->parseCore()->queryStoryBoard(item->text());

        auto children = node.first()->children();
        for (auto &it : children) {
            if (it->typeValue() != NODE_FRAGMENTREFERENCE) {
                contents += it->toString() + "\n";
            }
        }
    } else {
        auto node =
            core_ins->parseCore()->queryStoryBoard(item->parent()->text());
        auto point = core_ins->parseCore()->queryStoryFragmentRefer(
            node.first(), item->text().mid(1));

        auto children = point.first()->children();
        for (auto &it : children) {
            contents += it->toString() + "\n";
        }
    }

    detail_backend->setPlainText(contents);
}

QStandardItemModel *StoryboardsPresentModel::treeModel() const { return model_base; }

QTextDocument *StoryboardsPresentModel::detailBackend() const { return detail_backend; }

QString DataModel::StoryboardsPresentModel::name() const {
    return NAME(StoryboardsPresentModel);
}
