#include "yaml-cpp/yaml.h"

#include <cassert>
#include <iostream>
#include <vector>
#include <fstream>

int main(int argc, char **argv) {
    // yaml 增删改查

    /*
     * bool IsNull() const { return Type() == NodeType::Null; }         // 空类型
     * bool IsScalar() const { return Type() == NodeType::Scalar; }     // 纯量不可以在被细分的类型
     * bool IsSequence() const { return Type() == NodeType::Sequence; } // 数组/序列类型
     * bool IsMap() const { return Type() == NodeType::Map; }           // 类似C++中的map
     */

    // 定义一个节点
    YAML::Node node;
    // 初始化的节点是NULL类型
    assert(node.IsNull());
    // 赋值键值对的时候,它会转变为map类型
    node["key"] = "value";
    // 单纯的查询操作, 不会增加一个key
    if (node["key2"])
        std::cout << node["key2"].as<std::string>() << std::endl;
    // node 是一个map
    assert(node.IsMap());
    // node的seq下是一个Sequence类型,有两个参数
    node["seq"].push_back("first element");
    node["seq"].push_back("second element");
    // node->seq是一个Sequence类型
    assert(node["seq"].IsSequence());

    // 重新定义一个节点
    YAML::Node node2;
    // 如果你不给node2键值对,他是一个Sequence类型
    node2.push_back("first item");
    node2.push_back("second item");
    node2.push_back("third item");
    // node2是一个Sequence类型
    assert(node2.IsSequence());
    std::vector<int> v = {1, 3, 5, 7, 9};
    node2.push_back(v);
    // node2仍然是一个Sequence
    assert(node2.IsSequence());
    // 对于Sequence类型,你可以使用下标访问
    // 注意这里的as<T>是一个模板转换,node2[0]的tyoe是NodeType::Scalar
    assert(node2[0].as<std::string>() == "first item");
    // 使用迭代器访问
    for (auto value : node2) {
        // 他们的类型分别是NodeType::Scalar,NodeType::Scalar,NodeType::Scalar,NodeType::Sequence
        // 取值使用as<T>模板转换
        if (value.Type() == YAML::NodeType::Scalar) {
            std::cout << value.as<std::string>() << std::endl;
        } else if (value.Type() == YAML::NodeType::Sequence) {
            for (auto value2 : value) {
                std::cout << value2.as<int>() << std::endl;
            }
        }
    }

    std::cout << "========1=========" << std::endl;
    // 使用键值对赋值
    node2["key"] = "value";
    // 一旦使用键值对,它转变为Map类型
    assert(node2.IsMap());
    // 此时Sequence的下标变为它的key值
    assert(node2[0].as<std::string>() == "first item");
    // 将node_2作为node的一个子节点
    node["node2"] = node2;
    // 给已有的元素设置一个别名,类似指针
    node["pointer_to_first_element"] = node["seq"][0];
    // 通过这个指针访问那个元素
    assert(node["pointer_to_first_element"].as<std::string>() == "first element");
    // 你可以通过指定的元素来删除它
    node["seq"].remove(0);
    // 你也可以通过key来删除它
    node.remove("pointer_to_first_element");
    // 查看结果
    std::cout << node << std::endl;

    // yaml文件的保存与读取
    // Node可以使用文件流进行读取上面的std::cout已经证明了这一点,可以这样保存一个node
    std::ofstream file_out("/mnt/d/code/sylar/bin/conf/test.yaml");
    file_out << node << std::endl;
    file_out.close();
    std::cout << "========2=========" << std::endl;

    //读取一个yaml文件
    // 方式一
    std::ifstream file_in("/mnt/d/code/sylar/bin/conf/test.yaml");
    YAML::Node node3 = YAML::Load(file_in);
    std::cout << node3 << std::endl;
    file_in.close();
    std::cout << "========3=========" << std::endl;

    // 方式二
    YAML::Node node4 = YAML::LoadFile("/mnt/d/code/sylar/bin/conf/test.yaml");
    // 可以直接用下标访问
    std::cout << node4["node2"] << std::endl;
    std::cout << "========4=========" << std::endl;

    // 使用迭代器访问
    for (auto it = node4.begin(); it != node4.end(); it++) {
        std::cout << it->first << it->second << std::endl;
    }

    return 0;
}