#include "self_ptl_cfg.h"
#include "tinyxml2.h"

LOCAL const char *ele_Root = "Root";

LOCAL const char *ele_St = "St";
LOCAL const char *ele_Mx = "Mx";
LOCAL const char *ele_Co = "Co";
LOCAL const char *ele_Dd = "Dd";
LOCAL const char *ele_Param = "Param";

LOCAL const char *ele_Item = "Item";

LOCAL const char *attr_count = "count";
LOCAL const char *attr_saddr = "saddr";
LOCAL const char *attr_desc = "desc";
LOCAL const char *attr_inf = "inf";
LOCAL const char *attr_type = "type";
LOCAL const char *attr_default = "default";
LOCAL const char *attr_unit = "unit";
LOCAL const char *attr_min = "min";
LOCAL const char *attr_max = "max";
LOCAL const char *attr_step = "step";




LOCAL stru_self_ptl_cfg g_self_ptl_cfg;


typedef struct
{
    std::string type;
    std::vector<stru_self_ptl_cfg_base> *p_vec;
}stru_local_parse_base;

std::vector<stru_local_parse_base> g_local_parse_vec = 
{
    {ele_St, &g_self_ptl_cfg.st_vec},
    {ele_Mx, &g_self_ptl_cfg.mx_vec},
    {ele_Co, &g_self_ptl_cfg.co_vec},
    {ele_Dd, &g_self_ptl_cfg.dd_vec},
};

stru_self_ptl_cfg* self_ptl_cfg_get()
{
    return &g_self_ptl_cfg;
}

LOCAL int parse_base(tinyxml2::XMLElement *root) 
{
    if (root == nullptr)
    {
        MY_LOG_E("parse failed, root element is null");
        return -1;
    }
    
    for (const auto &local_parse : g_local_parse_vec)
    {
        tinyxml2::XMLElement *parent_ele = root->FirstChildElement(local_parse.type.c_str());
        if (parent_ele == nullptr)
        {
            MY_LOG_E("not found element %s", local_parse.type.c_str());
            continue;
        }

        const char *count_str = parent_ele->Attribute(attr_count);
        int count = 0;
        if (count_str != nullptr)        
        {
            count = atoi(count_str);    
        }
        else
        {
            MY_LOG_E("not found attribute %s in element %s", attr_count, local_parse.type.c_str());
            continue;
        }

        tinyxml2::XMLElement *item_ele = parent_ele->FirstChildElement(ele_Item);
        while (item_ele != nullptr)
        {
            stru_self_ptl_cfg_base cfg_base;
            const char *saddr = item_ele->Attribute(attr_saddr);
            const char *desc = item_ele->Attribute(attr_desc);
            int inf = 0;
            item_ele->QueryIntAttribute(attr_inf, &inf);

            if (saddr != nullptr)
            {
                cfg_base.saddr = saddr;
            }
            if (desc != nullptr)
            {
                cfg_base.desc = desc;
            }
            cfg_base.inf = inf;

            local_parse.p_vec->push_back(cfg_base);

            item_ele = item_ele->NextSiblingElement(ele_Item);
        }

        if(local_parse.p_vec->size() != count)
        {
            MY_LOG_E("count mismatch for element %s, expected %d, actual %d", 
                    local_parse.type.c_str(), count, (int)local_parse.p_vec->size());
            return -1;
        }
    }

    return 0;
}

int self_ptl_cfg_parse(const std::string &path)
{
    // 解析XML文件

    tinyxml2::XMLDocument doc;
    if (doc.LoadFile(path.c_str()) != tinyxml2::XML_SUCCESS)
    {
        MY_LOG_E("Failed to load XML file: %s", path.c_str());
        return -1;
    }

    tinyxml2::XMLElement *root = doc.RootElement();
    if (root == nullptr)
    {
        MY_LOG_E("Failed to get root element");
        return -1;
    }

    if(parse_base(root) != 0)
    {
        MY_LOG_E("Failed to parse base elements");
        return -1;
    }


    return 0;
}
