#include "DMAcc.h"
#include "Common.h"
#include "treemanager/IMOTreeManager.h"
#include "TNDSMgmtTree/TNDSCreator.h"
#include "TNDSMgmtTree/TNDSExtractor.h"

namespace NS_DM_Client
{
    enum DMAccEnum
    {
        e_AppID = 0,
        e_ServerID,
        e_Name,
        e_PrefConRef,
        e_AAuthPref,
        e_ToConRef,
        e_AppAuth,
        e_AppAddr
    };

    enum DMAccImplEnum
    {
        e_DMAcc = 0
    };

    const String DMAccFieldPath[] =
    {
        "./DMAcc"
    };

    const String DMAccFieldName[] =
    {
        "AppID",
        "ServerID",
        "Name",
        "PrefConRef",
        "AAuthPref",
        "ToConRef",
        "AppAuth",
        "AppAddr"
    };
    //-------------------------------------------------------------------------------------------

    const char* DMAccToConfFieldName[] =
    {
        "ConRef"
    };
    //-------------------------------------------------------------------------------------------

    enum DMAccAppAddrEnum
    {
        e_Addr = 0,
        e_AddrType,
        e_PortNbr
    };

    const char* DMAccAppAddrFieldName[] =
    {
        "Addr",
        "AddrType",
        "Port/0/PortNbr"
    };
    //-------------------------------------------------------------------------------------------

    enum DMAccAppAuthEnum
    {
        e_AAuthLevel = 0,
        e_AAuthType,
        e_AAuthName,
        e_AAuthSecret,
        e_AAuthData
    };

    const char* DMAccAppAuthFieldName[] =
    {
        "AAuthLevel",
        "AAuthType",
        "AAuthName",
        "AAuthSecret",
        "AAuthData"
    };
    //-------------------------------------------------------------------------------------------

    bool AppAddr::Serialize(const String& basePathName, IMOTreeManager& treeManager) const
    {
        bool res = NS_DM_Client::Serialize(basePathName + S_slash + DMAccAppAddrFieldName[e_Addr], m_Addr, treeManager);
        res &= NS_DM_Client::Serialize(basePathName + S_slash + DMAccAppAddrFieldName[e_AddrType], m_AddrType, treeManager);
        res &= NS_DM_Client::Serialize(basePathName + S_slash + DMAccAppAddrFieldName[e_PortNbr], m_PortNbr, treeManager, S_intFormat);
        return res;
    }
    //-------------------------------------------------------------------------------------------

    bool AppAddr::Deserialize(const String& basePathName, IMOTreeManager& treeManager)
    {
        bool res = NS_DM_Client::Deserialize(basePathName + S_slash + DMAccAppAddrFieldName[e_Addr], m_Addr, treeManager);
        res &= NS_DM_Client::Deserialize(basePathName + S_slash + DMAccAppAddrFieldName[e_AddrType], m_AddrType, treeManager);
        res &= NS_DM_Client::Deserialize(basePathName + S_slash + DMAccAppAddrFieldName[e_PortNbr], m_PortNbr, treeManager);
        return res;
    }
    //-------------------------------------------------------------------------------------------

    bool AppAddr::Serialize(const String& basePathName, TNDSCreator& tree) const
    {
        tree.Append(basePathName, DMAccAppAddrFieldName[e_Addr], m_Addr);
        tree.Append(basePathName, DMAccAppAddrFieldName[e_AddrType], m_AddrType);
        tree.Append(basePathName, DMAccAppAddrFieldName[e_PortNbr], m_PortNbr);
        return true;
    }
    //-------------------------------------------------------------------------------------------

    bool AppAddr::Deserialize(const String& basePathName, TNDSExtractor& tree)
    {
        tree.GetValue(basePathName, DMAccAppAddrFieldName[e_Addr], m_Addr);
        tree.GetValue(basePathName, DMAccAppAddrFieldName[e_AddrType], m_AddrType);
        tree.GetValue(basePathName, DMAccAppAddrFieldName[e_PortNbr], m_PortNbr);
        return true;
    }
    //-------------------------------------------------------------------------------------------

    bool AppAuth::Serialize(const String& basePathName, IMOTreeManager& treeManager) const
    {
        bool res = NS_DM_Client::Serialize(basePathName + S_slash + DMAccAppAuthFieldName[e_AAuthLevel], m_AAuthLevel, treeManager);
        res &= NS_DM_Client::Serialize(basePathName + S_slash + DMAccAppAuthFieldName[e_AAuthType], m_AAuthType, treeManager);
        res &= NS_DM_Client::Serialize(basePathName + S_slash + DMAccAppAuthFieldName[e_AAuthName], m_AAuthName, treeManager);
        res &= NS_DM_Client::Serialize(basePathName + S_slash + DMAccAppAuthFieldName[e_AAuthSecret], m_AAuthSecret, treeManager);
        res &= NS_DM_Client::Serialize(basePathName + S_slash + DMAccAppAuthFieldName[e_AAuthData], m_AAuthData, treeManager);
        return res;
    }
    //-------------------------------------------------------------------------------------------

    bool AppAuth::Deserialize(const String& basePathName, IMOTreeManager& treeManager)
    {
        bool res = NS_DM_Client::Deserialize(basePathName + S_slash + DMAccAppAuthFieldName[e_AAuthLevel], m_AAuthLevel, treeManager);
        res &= NS_DM_Client::Deserialize(basePathName + S_slash + DMAccAppAuthFieldName[e_AAuthType], m_AAuthType, treeManager);
        res &= NS_DM_Client::Deserialize(basePathName + S_slash + DMAccAppAuthFieldName[e_AAuthName], m_AAuthName, treeManager);
        res &= NS_DM_Client::Deserialize(basePathName + S_slash + DMAccAppAuthFieldName[e_AAuthSecret], m_AAuthSecret, treeManager);
        res &= NS_DM_Client::Deserialize(basePathName + S_slash + DMAccAppAuthFieldName[e_AAuthData], m_AAuthData, treeManager);
        return res;
    }
    //-------------------------------------------------------------------------------------------

    bool AppAuth::Serialize(const String& basePathName, TNDSCreator& tree) const
    {
        tree.Append(basePathName, DMAccAppAuthFieldName[e_AAuthLevel], m_AAuthLevel);
        tree.Append(basePathName, DMAccAppAuthFieldName[e_AAuthType], m_AAuthType);
        tree.Append(basePathName, DMAccAppAuthFieldName[e_AAuthName], m_AAuthName);
        tree.Append(basePathName, DMAccAppAuthFieldName[e_AAuthSecret], m_AAuthSecret);
        tree.Append(basePathName, DMAccAppAuthFieldName[e_AAuthData], m_AAuthData);
        return true;
    }
    //-------------------------------------------------------------------------------------------

    bool AppAuth::Deserialize(const String& basePathName, TNDSExtractor& tree)
    {
        tree.GetValue(basePathName, DMAccAppAuthFieldName[e_AAuthLevel], m_AAuthLevel);
        tree.GetValue(basePathName, DMAccAppAuthFieldName[e_AAuthType], m_AAuthType);
        tree.GetValue(basePathName, DMAccAppAuthFieldName[e_AAuthName], m_AAuthName);
        tree.GetValue(basePathName, DMAccAppAuthFieldName[e_AAuthSecret], m_AAuthSecret);
        tree.GetValue(basePathName, DMAccAppAuthFieldName[e_AAuthData], m_AAuthData);
        return true;
    }
    //-------------------------------------------------------------------------------------------

    bool DMAccImpl::Serialize(const String& basePathName, IMOTreeManager& treeManager) const
    {
        bool res = NS_DM_Client::Serialize(basePathName + S_slash + DMAccFieldName[e_AppID], m_AppID, treeManager);
        res &= NS_DM_Client::Serialize(basePathName + S_slash + DMAccFieldName[e_ServerID], m_ServerID, treeManager);
        res &= NS_DM_Client::Serialize(basePathName + S_slash + DMAccFieldName[e_Name], m_Name, treeManager);
        res &= NS_DM_Client::Serialize(basePathName + S_slash + DMAccFieldName[e_PrefConRef], m_PrefConRef, treeManager);
        res &= NS_DM_Client::Serialize(basePathName + S_slash + DMAccFieldName[e_AAuthPref], m_AAuthPref, treeManager);

        // ToConRef
        for (size_t i = 0; i != m_ToConRef.size(); ++i)
        {
            res &= NS_DM_Client::Serialize(basePathName + S_slash + DMAccFieldName[e_ToConRef] + S_slash + ToString(i) + S_slash + 
                DMAccToConfFieldName[0], m_ToConRef[i], treeManager);
        }

        // AppAddr
        for (size_t i = 0; i != m_AppAddr.size(); ++i)
        {
            res &= m_AppAddr[i].Serialize(basePathName + S_slash + DMAccFieldName[e_AppAddr] + S_slash + ToString(i), treeManager);
        }

        // AppAuth
        for (size_t i = 0; i != m_AppAuth.size(); ++i)
        {
            res &= m_AppAuth[i].Serialize(basePathName + S_slash + DMAccFieldName[e_AppAuth] + S_slash + ToString(i), treeManager);
        }
        return res;
    }
    //-------------------------------------------------------------------------------------------

    bool DMAccImpl::Deserialize(const String& basePathName, IMOTreeManager& treeManager)
    {
        bool res = NS_DM_Client::Deserialize(basePathName + S_slash + DMAccFieldName[e_AppID], m_AppID, treeManager);
        res &= NS_DM_Client::Deserialize(basePathName + S_slash + DMAccFieldName[e_ServerID], m_ServerID, treeManager);

        // Name, PrefConRef and AAuthRef are not mandatory and can be missing in the MO tree.
        NS_DM_Client::Deserialize(basePathName + S_slash + DMAccFieldName[e_Name], m_Name, treeManager);
        NS_DM_Client::Deserialize(basePathName + S_slash + DMAccFieldName[e_PrefConRef], m_PrefConRef, treeManager);
        NS_DM_Client::Deserialize(basePathName + S_slash + DMAccFieldName[e_AAuthPref], m_AAuthPref, treeManager);

        // ToConRef
        size_t i = 0;
        String uri(basePathName + S_slash + DMAccFieldName[e_ToConRef] + S_slash + ToString(i) + S_slash + DMAccToConfFieldName[0]);
        while (res && treeManager.Exist(uri))
        {
            String item;
            res &= NS_DM_Client::Deserialize(uri, item, treeManager);
            m_ToConRef.push_back(item);
            uri = basePathName + S_slash + DMAccFieldName[e_ToConRef] + S_slash + ToString(++i) + S_slash + DMAccToConfFieldName[0];
        }

        // AppAddr
        i = 0;
        uri = basePathName + S_slash + DMAccFieldName[e_AppAddr] + S_slash + ToString(i);
        while (res && treeManager.Exist(uri))
        {
            AppAddr item;
            res &= item.Deserialize(uri, treeManager);
            m_AppAddr.push_back(item);
            uri = basePathName + S_slash + DMAccFieldName[e_AppAddr] + S_slash + ToString(++i);
        }

        // AppAuth
        i = 0;
        uri = basePathName + S_slash + DMAccFieldName[e_AppAuth] + S_slash + ToString(i);
        while (res && treeManager.Exist(uri))
        {
            AppAuth item;
            res &= item.Deserialize(uri, treeManager);
            m_AppAuth.push_back(item);
            uri = basePathName + S_slash + DMAccFieldName[e_AppAuth] + S_slash + ToString(++i);
        }
        return res;
    }
    //-------------------------------------------------------------------------------------------

    bool DMAccImpl::Serialize(const String& basePathName, TNDSCreator& tree) const
    {
        tree.Append(basePathName, DMAccFieldName[e_AppID], m_AppID);
        tree.Append(basePathName, DMAccFieldName[e_ServerID], m_ServerID);
        tree.Append(basePathName, DMAccFieldName[e_Name], m_Name);
        tree.Append(basePathName, DMAccFieldName[e_PrefConRef], m_PrefConRef);
        tree.Append(basePathName, DMAccFieldName[e_AAuthPref], m_AAuthPref);

        // ToConRef
        bool res = true;
        for (size_t i = 0; i != m_ToConRef.size(); ++i)
        {
            tree.Append(basePathName + S_slash + DMAccFieldName[e_ToConRef], ToString(i));
            tree.Append(basePathName + S_slash + DMAccFieldName[e_ToConRef] + S_slash + ToString(i), 
                DMAccToConfFieldName[0], m_ToConRef[i]);
        }

        // AppAddr
        for (size_t i = 0; i != m_AppAddr.size(); ++i)
        {
            tree.Append(basePathName + S_slash + DMAccFieldName[e_AppAddr], ToString(i));
            res &= m_AppAddr[i].Serialize(basePathName + S_slash + DMAccFieldName[e_AppAddr] + S_slash + ToString(i), tree);
        }

        // AppAuth
        for (size_t i = 0; i != m_AppAuth.size(); ++i)
        {
            tree.Append(basePathName + S_slash + DMAccFieldName[e_AppAuth], ToString(i));
            res &= m_AppAuth[i].Serialize(basePathName + S_slash + DMAccFieldName[e_AppAuth] + S_slash + ToString(i), tree);
        }
        return res;
    }
    //-------------------------------------------------------------------------------------------

    bool DMAccImpl::Deserialize(const String& basePathName, TNDSExtractor& tree)
    {
        tree.GetValue(basePathName, DMAccFieldName[e_AppID], m_AppID);
        tree.GetValue(basePathName, DMAccFieldName[e_ServerID], m_ServerID);
        tree.GetValue(basePathName, DMAccFieldName[e_Name], m_Name);
        tree.GetValue(basePathName, DMAccFieldName[e_PrefConRef], m_PrefConRef);
        tree.GetValue(basePathName, DMAccFieldName[e_AAuthPref], m_AAuthPref);

        // ToConRef
        String uri(basePathName + S_slash + DMAccFieldName[e_ToConRef]);
        m_ToConRef.resize(tree.GetCount(uri));
        for (size_t i = 0; i != m_ToConRef.size(); ++i)
        {
            tree.GetValue(uri + S_slash + ToString(i), DMAccToConfFieldName[0], m_ToConRef[i]);
        }

        // AppAddr
        uri = basePathName + S_slash + DMAccFieldName[e_AppAddr];
        m_AppAddr.resize(tree.GetCount(uri));
        bool res = true;
        for (size_t i = 0; i != m_AppAddr.size(); ++i)
        {
            res &= m_AppAddr[i].Deserialize(uri + S_slash + ToString(i), tree);
        }

        // AppAuth
        uri = basePathName + S_slash + DMAccFieldName[e_AppAuth];
        m_AppAuth.resize(tree.GetCount(uri));
        for (size_t i = 0; i != m_AppAuth.size(); ++i)
        {
            res &= m_AppAuth[i].Deserialize(uri + S_slash + ToString(i), tree);
        }
        return res;
    }
    //-------------------------------------------------------------------------------------------


    bool DMAcc::Serialize(IMOTreeManager& treeManager) const
    {
        bool res = true;
        for (size_t i = 0; i != m_DMAccImpl.size(); ++i)
        {
            res = m_DMAccImpl[i].Serialize(DMAccFieldPath[e_DMAcc] + S_slash + ToString(i), treeManager);
        }
        return res;
    }
    //-------------------------------------------------------------------------------------------

    bool DMAcc::Deserialize(IMOTreeManager& treeManager)
    {
        bool res = true;
        size_t i = 0;
        String uri(DMAccFieldPath[e_DMAcc] + S_slash + ToString(i));
        while (res && treeManager.Exist(uri))
        {
            DMAccImpl dmAccImpl;
            res &= dmAccImpl.Deserialize(uri, treeManager);
            m_DMAccImpl.push_back(dmAccImpl);
            uri = DMAccFieldPath[e_DMAcc] + S_slash + ToString(++i);
        }
        return res;
    }
    //-------------------------------------------------------------------------------------------

    bool DMAcc::Serialize(String& xml) const
    {
        bool res = true;
        TNDSCreator tree;
        for (size_t i = 0; i != m_DMAccImpl.size(); ++i)
        {
            tree.Append(DMAccFieldPath[e_DMAcc], ToString(i));
            res &= m_DMAccImpl[i].Serialize(DMAccFieldPath[e_DMAcc] + S_slash + ToString(i), tree);
        }
        tree.Get(xml);
        return res;
    }
    //-------------------------------------------------------------------------------------------

    bool DMAcc::Deserialize(const String& xml)
    {
        TNDSExtractor tree(xml);
        bool res = true;
        String uri(DMAccFieldPath[e_DMAcc]);
        m_DMAccImpl.resize(tree.GetCount(uri));
        for (size_t i = 0; i != m_DMAccImpl.size(); ++i)
        {
            res &= m_DMAccImpl[i].Deserialize(uri + S_slash + ToString(i), tree);
        }
        return res;
    }

}
