/* src/KMBuilderManifest.h
 *
 * Copyright (C) 2024 OpenKylin, Inc
 */

#ifndef __BUILDER_MANIFEST_H__
#define __BUILDER_MANIFEST_H__

#include <string>
#include <vector>
#include <memory>
#include <optional>
#include <map>
#include <yaml-cpp/yaml.h>

#include "KMBuilderModule.h"

#define PACKGE_KIND_APP "app"
#define PACKGE_KIND_BASE "base"
#define PACKGE_KIND_RUNTIME "runtime"

/**
 * @brief : 构建清单类
 */ 
class KMBuilderManifest : public std::enable_shared_from_this<KMBuilderManifest>
{
public:
    /**
     * 清单内部类，用于描述package属性
     */ 
    struct Package
    {
        // appid，形如：top.openkylin.Calculator，必须
        std::string m_id;
        // 名称，形如：Calculator；非必须
        std::string m_name;
        // 包版本，必须
        std::string m_version;
        // 包类型，如：app、runtime、base等，必须
        std::string m_kind;
        // 包描述信息；非必须
        std::string m_description;
        //description[zh_CN]包描述信息；非必须
        std::map<std::string, std::string> m_descriptions;
        //name[zh_CN] 展示名称；非必须
        std::map<std::string, std::string> m_names;
        
    };

public:
    virtual ~KMBuilderManifest();

    /**
     * @brief : 工厂函数，根据yaml格式的清单文件创建清单对象
     * @param : [in] yaml，yaml清单文件
     * @return: std::shared_ptr<KMBuilderManifest>，创建成功则关联对象；
     * @throws: KMException，创建失败则函数抛出异常
     */  
    [[nodiscard]] static std::shared_ptr<KMBuilderManifest> loadFromYAML(const std::string& yaml);

private:
    KMBuilderManifest(YAML::Node);

    // 解析清单属性
    void parseFromYAML();
    // 解析清单的modules属性
    std::vector<std::shared_ptr<KMBuilderModule>> parseModules(const YAML::Node& modules);
    // 加载清单共享节点(共享模块、共享源)
    YAML::Node loadShareNode(const YAML::Node& shareNode);
    // 解析清单中module下的sources属性
    std::vector<std::shared_ptr<KMBuilderSource>> parseSources(const YAML::Node& sources);
    // 解析构建选项
    std::shared_ptr<KMBuildOptions> parseBuildOptions(YAML::Node &node);
    // 验证必设字段
    void validate();

public:
    // 清单属性域

    // 清单规范版本，必须
    std::string m_version;
    // 包基础信息，必须
    Package m_package;
    // 包中可执行程序列表，kaiming run时默认运行第一个，故需要注意书写顺序，建议只配置一个核心可执行程序；非必须
    std::vector<std::string> m_commands;
    // 渠道，如：stable；非必须
    std::string m_channel;
    // 权限；非必须
    std::vector<std::string> m_permissions;
    // 模块类型，如：binary、devel(只有base和runtime才有，app不提供开发库)；非必须
    std::string m_module;
    // base，如：dev.openkylin.Base/23.0.0；必须
    std::string m_base;
    // 运行时，如：dev.openkylin.Runtime/23.0.0；非必须
    std::string m_runtime;
    // 构建模块，必须
    std::vector<std::shared_ptr<KMBuilderModule>> m_modules;
    // 环境变量；非必须
    std::map<std::string, std::string> m_envs;
    
private:
    // 数据成员域

    // YAML文件
    std::string m_yaml;
    // YAML根节点
    YAML::Node m_rootNode;
    // 反编列base目录
    std::string m_demarshalBaseDir;
};

#endif /* __BUILDER_INIT_H__ */
