#include "iec_cfg_parse.h"
#include <tinyxml2.h>

using namespace tinyxml2;

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_Ao = "Ao";
LOCAL const char *ele_Param = "Param";
LOCAL const char *ele_Signal = "Signal";
LOCAL const char *ele_Item = "Item";

LOCAL const char *attr_saddr = "saddr";
LOCAL const char *attr_desc = "desc";
LOCAL const char *attr_link = "link";
LOCAL const char *attr_inf = "inf";
LOCAL const char *attr_type = "type";


LOCAL stru_iec_cfg g_iec_cfg = {};

typedef struct 
{
    std::string ele_type;
    std::vector<stru_cfg_base> *p_vec;
    uint8_t data_type;
}stru_local_parse;

LOCAL std::vector<stru_local_parse> g_local_parse_vec = 
{
    {ele_St, &g_iec_cfg.vec_st, DATA_TYPE_U8},
    {ele_Mx, &g_iec_cfg.vec_mx, DATA_TYPE_F32},
    {ele_Co, &g_iec_cfg.vec_co, DATA_TYPE_U8},
    {ele_Dd, &g_iec_cfg.vec_dd, DATA_TYPE_F32},
    {ele_Ao, &g_iec_cfg.vec_ao, 0},
    {ele_Param, &g_iec_cfg.vec_param, 0},
};


LOCAL int parse_base(XMLElement *root)
{
    if (root == nullptr)
    {
        MY_LOG_E("root is nullptr");
        return -1;
    }

    for(uint32_t i = 0; i < g_local_parse_vec.size(); i++)
    {
        XMLElement *parent_ele = root->FirstChildElement(g_local_parse_vec[i].ele_type.c_str());
        if (parent_ele == nullptr)
        {
            continue;
        }
    
        XMLElement *signal_ele = parent_ele->FirstChildElement(ele_Signal);
        while(signal_ele != nullptr)
        {
            stru_cfg_base cfg_base = {};
            const char *saddr = signal_ele->Attribute(attr_saddr);
            const char *desc = signal_ele->Attribute(attr_desc);
            const char *link = signal_ele->Attribute(attr_link);
            const char *inf = signal_ele->Attribute(attr_inf);
            const char *type = signal_ele->Attribute(attr_type);

            cfg_base.saddr = (saddr == nullptr ? "" : std::string(saddr));
            cfg_base.desc = (desc == nullptr ? "" : std::string(desc));
            cfg_base.link = (link == nullptr ? "" : std::string(link));
            cfg_base.inf = (inf == nullptr ? 0 : atoi(inf));
            cfg_base.type = (type == nullptr ? 0 : dc_get_data_type_id_by_str(type));

            if(cfg_base.type == 0)
            {
                cfg_base.type = g_local_parse_vec[i].data_type;
            }

            g_local_parse_vec[i].p_vec->push_back(cfg_base);

            signal_ele = signal_ele->NextSiblingElement(ele_Signal);
        }
    }

    return 0;
}






stru_iec_cfg *iec_cfg_ptr_get(void)
{
    return &g_iec_cfg;
}

int iec_cfg_parse(const std::string &path)
{

    XMLDocument doc;

    if (doc.LoadFile(path.c_str()) != XML_SUCCESS)
    {
        MY_LOG_E("LoadFile failed, path: %s", path.c_str());
        return -1;
    }

    XMLElement *root = doc.RootElement();
    if (root == nullptr)
    {
        MY_LOG_E("RootElement is nullptr");
        return -1;
    }

    if(0 != parse_base(root))
    {
        MY_LOG_E("parse_base failed");
        return -1;
    }

    return 0;
}

