/*
 * This file was generated by qdbusxml2cpp version 0.8
 * Command line was: qdbusxml2cpp dbus.xml -a dbus_adaptor
 *
 * qdbusxml2cpp is Copyright (C) 2020 The Qt Company Ltd.
 *
 * This is an auto-generated file.
 * Do not edit! All changes made to it will be lost.
 */


#include <QtCore/QMetaObject>
#include <QtCore/QByteArray>
#include <QtCore/QList>
#include <QtCore/QMap>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QVariant>

#include "kylin_netctrol_server_interface.h"
#include "kylin_common.h"
#include "kylin_hedron_log.h"
/*
 * Implementation of adaptor class NetCtrlAdaptor
 */



#define KYLIN_NETCTROL_CFG_PATH  "/etc/NetworkManager/kylin_nm_ctrl.ini"



st_ItemCfgInfo gItemCfgInfo[]=
{
    {(char *)NET_CTRL_IP4_NAME,(char *)"netIPV4ModifyCtrol",(void *)g_variant_new_boolean(false),KEYLIN_CFG_VARIANT,NULL,NULL,NULL,NULL},//IPV4模块的ip修改管控
    {(char *)NET_CTRL_IP6_NAME,(char *)"netIPV6ModifyCtrol",(void *)g_variant_new_boolean(false),KEYLIN_CFG_VARIANT,NULL,NULL,NULL,NULL},//IPV6模块的ip修改管控
    {(char *)NET_CTRL_DNS_NAME,(char *)"netIPV4DNSModifyCtrol",(void *)g_variant_new_boolean(false),KEYLIN_CFG_VARIANT,NULL,NULL,NULL,NULL},//DNS模块的修改管控
    {(char *)NET_CTRL_DNS_NAME,(char *)"netIPV6DNSModifyCtrol",(void *)g_variant_new_boolean(false),KEYLIN_CFG_VARIANT,NULL,NULL,NULL,NULL},//DNS模块的修改管控
    {(char *)NET_CTRL_CONNECT_NAME,(char *)"netWireWirelessSyncConnectCtrol",(void *)g_variant_new_boolean(false),KEYLIN_CFG_VARIANT,NULL,NULL,NULL,NULL},//连接模块的同时多连接管控（双跨管控）networkmanager没有对应配置
    {(char *)NET_CTRL_IP4_NAME,(char *)"netMaskModifyCtrol",(void *)g_variant_new_boolean(false),KEYLIN_CFG_VARIANT,NULL,NULL,NULL,NULL},//IPV4模块的掩码修改管控
    {(char *)NET_CTRL_IP4_NAME,(char *)"netGwModifyCtrol",(void *)g_variant_new_boolean(false),KEYLIN_CFG_VARIANT,NULL,NULL,NULL,NULL},//IPV4模块的网关修改管控
    {(char *)NET_CTRL_IP6_NAME,(char *)"netMaskModifyCtrol",(void *)g_variant_new_boolean(false),KEYLIN_CFG_VARIANT,NULL,NULL,NULL,NULL},//IPV6模块的掩码修改管控
    {(char *)NET_CTRL_IP6_NAME,(char *)"netGwModifyCtrol",(void *)g_variant_new_boolean(false),KEYLIN_CFG_VARIANT,NULL,NULL,NULL,NULL},//IPV6模块的网关修改管控
    {(char *)NET_CTRL_LOG_NAME,(char *)"netMonitorEnable",(void *)g_variant_new_boolean(false),KEYLIN_CFG_VARIANT,NULL,NULL,NULL,NULL},//网络ip gw等变化上报使能

};

#ifdef __cplusplus
extern "C" {
#endif

struct T_NetCtrlLogInfo
{
    char *level;
    char *messag;
};

void netCtrlAsyncSendHedronLog(void *args)
{
    struct T_NetCtrlLogInfo *pNetCtrlLogInfo=(struct T_NetCtrlLogInfo *)args;
    if(!pNetCtrlLogInfo || !pNetCtrlLogInfo->level || !pNetCtrlLogInfo->messag)
    {
        KYLIN_COMMON_LOG(_LOGL_ERR,"invalid args!");
        return;
    }
    kylinSendHedronMessage(pNetCtrlLogInfo->level,pNetCtrlLogInfo->messag);
    if(pNetCtrlLogInfo->level) g_free(pNetCtrlLogInfo->level);
    if(pNetCtrlLogInfo->messag) g_free(pNetCtrlLogInfo->messag);
    free(pNetCtrlLogInfo);
}

#ifdef __cplusplus
}
#endif

NetCtrlAdaptor::NetCtrlAdaptor(QObject *parent): QObject(parent)
{
    initCfg();
    mAsyncHandle=kylinAsyncTaskCreate(KYLIN_ASYNC_DEFAULT_THREAD_NUM);
}

NetCtrlAdaptor::~NetCtrlAdaptor()
{
    // destructor
   if(mCfgHandle) kylinCfgDestroy(mCfgHandle);
   if(mAsyncHandle) kylinAsyncTaskRelease(mAsyncHandle);
}

int NetCtrlAdaptor::fristCreatCfgInfo()
{
    int cnt=sizeof(gItemCfgInfo)/sizeof(st_ItemCfgInfo);
    int i=0;
    st_ItemCfgInfo *pItemCfgInfo=NULL;
    for(i=0;i<cnt;i++)
    {
        pItemCfgInfo=&gItemCfgInfo[i];
        if(pItemCfgInfo->dataType==KEYLIN_CFG_VARIANT)
        {
            if(pItemCfgInfo->data)
            {
                st_ItemCfgInfo * pItemNewCfgInfo=kylinCfgNewCommonItem(pItemCfgInfo->modName,pItemCfgInfo->itemName,g_variant_ref_sink((GVariant *)pItemCfgInfo->data));
                kylinCfgSetItem(mCfgHandle,pItemNewCfgInfo);
            }
        }
        else
        {
            // 其他类型TODO
             qDebug() << "not support";
             return -1;
        }
    }
    return 0;
    // destructor
}

void NetCtrlAdaptor::initServer()
{
    bool isServiceRegistered = QDBusConnection::systemBus().interface()->isServiceRegistered(QStringLiteral("com.kylin.networkCtrol"));
    if(!isServiceRegistered)
    {
       registerService();
    }
}

void NetCtrlAdaptor::initCfg()
{

    mCfgHandle=kylinCfgCreate();
    if(mCfgHandle)
    {
         if(kylinCfgLoad(mCfgHandle,QString(KYLIN_NETCTROL_CFG_PATH).toLocal8Bit().data())==COMMON_FILE_NOT_EXIST)
         {
             fristCreatCfgInfo();
             kylinCfgFlush(mCfgHandle);//配置文件在dbus服务端刷合理点
         }
         kylinCfgShow(mCfgHandle);
    }
    else
    {
        KYLIN_COMMON_LOG(_LOGL_ERR,"create failed!");
    }
}


bool NetCtrlAdaptor::registerService()
{

    QDBusConnection conn = QDBusConnection::systemBus();
    auto reply = conn.interface()->registerService(QStringLiteral("com.kylin.networkCtrol"),
                                                          QDBusConnectionInterface::ReplaceExistingService,
                                                          QDBusConnectionInterface::DontAllowReplacement);
    if (reply.value() == QDBusConnectionInterface::ServiceNotRegistered) {
        KYLIN_COMMON_LOG(_LOGL_ERR,"registerService /com/kylin/networkCtrol failed!");
        return false;
    }

    bool res = QDBusConnection::systemBus().registerObject("/com/kylin/networkCtrol", this,QDBusConnection::ExportAllSlots | QDBusConnection::ExportAllSignals);
    if (!res) {
        QDBusConnection::systemBus().interface()->unregisterService(QStringLiteral("com.kylin.networkCtrol"));
        KYLIN_COMMON_LOG(_LOGL_ERR,"registerObject /com/kylin/networkCtrol failed!");
    }
    KYLIN_COMMON_LOG(_LOGL_INFO,"registerObject /com/kylin/networkCtrol success!");

    return res;
}

GVariant* NetCtrlAdaptor::transQvariantToGvariant(QVariant &qVariant)
{
    GVariant* gVariant = nullptr;

    switch (qVariant.type()) {
    case QVariant::Int:
        gVariant = g_variant_new_int32(qVariant.toInt());
        break;
    case QVariant::UInt:
        gVariant = g_variant_new_uint32(qVariant.toUInt());
        break;
    case QVariant::Bool:
        gVariant = g_variant_new_boolean(qVariant.toBool());
        break;
    case QVariant::Double:
        gVariant = g_variant_new_double(qVariant.toDouble());
        break;
    case QVariant::String:
        gVariant = g_variant_new_string(qVariant.toString().toLocal8Bit().data());
        break;
    // 添加其他QVariant类型的转换
    default:
        // 其他类型TODO
        // 默认情况下，不支持的类型返回NULL
        gVariant = nullptr;
        break;
    }
    return gVariant;
}

QVariant NetCtrlAdaptor::transGvariantToQvariant(GVariant *gVariant)
{
    //const gchar * type = g_variant_get_type_string(gvariant);
    GVariantClass type=g_variant_classify(gVariant);
    // 根据类型进行转换

    switch(static_cast<int>(type))
    {
    case G_VARIANT_CLASS_BOOLEAN:
        if(g_variant_get_boolean(gVariant))
        {
            return QVariant(true);
        }
        else
        {
           return QVariant(false);
        }
        break;
    case G_VARIANT_CLASS_INT32:
         return QVariant(g_variant_get_int32(gVariant));
    case G_VARIANT_CLASS_UINT32:
        return QVariant(g_variant_get_uint32(gVariant));
    case G_VARIANT_CLASS_STRING:
       return QVariant(g_variant_get_string(gVariant,NULL));
    case G_VARIANT_CLASS_INT64:
         return QVariant((long long)g_variant_get_int64(gVariant));
    case G_VARIANT_CLASS_UINT64:
        return QVariant((unsigned long long)g_variant_get_uint64(gVariant));
    }

    // 其他类型TODO
    // 如果类型不匹配，返回一个空的QVariant

    return QVariant();
}


int NetCtrlAdaptor::setNetContrlRule(const QString modName,const QVariantMap value)
{
    KYLIN_COMMON_LOG(_LOGL_INFO,"setNetContrlRule ruleName:%s \n",modName.toLocal8Bit().data());
    GVariant* gVariant = nullptr;
    QString msg;

    if(value.isEmpty() || modName.isEmpty())
    {
        KYLIN_COMMON_LOG(_LOGL_ERR,"setNetContrlRule invalid parm");
        return NETCT_INVALID_MODE;
    }

    for (auto it = value.cbegin(); it != value.cend(); ++it) {
        QString key = it.key();
        QVariant value = it.value();

        st_ItemCfgInfo *pItemCfgInfo=kylinCfgGetItem(mCfgHandle,modName.toLocal8Bit().data(),key.toLocal8Bit().data());
        if(!pItemCfgInfo)
        {
            KYLIN_COMMON_LOG(_LOGL_ERR,"not support modName:%s",modName.toLocal8Bit().data());
            msg=QString().sprintf("set %s failed,not support",modName.toLocal8Bit().data());;
            return NETCT_INVALID_RULE;
        }

        if(pItemCfgInfo->dataType==KEYLIN_CFG_VARIANT)
        {
            gVariant=transQvariantToGvariant(value);
            if(!gVariant)
            {
                return NETCT_PARM_MISMATCH;
            }

            gboolean ret=g_variant_equal(gVariant,(GVariant*)pItemCfgInfo->data);
            if(!ret)
            {
                st_ItemCfgInfo *pItemCfgInfo=kylinCfgNewCommonItem(modName.toLocal8Bit().data(),key.toLocal8Bit().data(),gVariant);
                if(kylinCfgSetItem(mCfgHandle,pItemCfgInfo))
                {
                    return NETCT_DO_FAILED;
                }
            }
            else
            {
                g_variant_unref(gVariant);
            }
        }
        else
        {
            KYLIN_COMMON_LOG(_LOGL_ERR,"not support");
            //TODO 需要自己加自定义数据转换 暂时没用到
        }
    }
    kylinCfgFlush(mCfgHandle);//刷配置文件
    Q_EMIT sigNetContrlRuleChanged(modName,value);
    return NETCT_SUCCESS;
}

void  NetCtrlAdaptor::getNetContrlRule(const QString modName,QVariantMap &value,int &errCode)
{
    GList * list=NULL, *iter=NULL;
    errCode=0;
   // kylinCfgGetItem(mCfgHandle,modName.toLocal8Bit().data(),);
    KYLIN_COMMON_LOG(_LOGL_INFO,"getNetContrlRule modName:%s",modName.toLocal8Bit().data());
    list=kylinCfgGetModItems(mCfgHandle,modName.toLocal8Bit().data());
    if(!list)
    {
        errCode=NETCT_INVALID_MODE;
        return;
    }

    for (iter = list; iter; iter = iter->next)
    {
       //KYLIN_COMMON_LOG(_LOGL_DEBUG,"getNetContrlRule iter:%p ",iter);
       st_ItemCfgInfo *pItemCfgInfo=( st_ItemCfgInfo *)iter->data;
       if(pItemCfgInfo->dataType==KEYLIN_CFG_VARIANT)
       {
           QVariant data=transGvariantToQvariant((GVariant*)pItemCfgInfo->data);
           if(data.isNull())
           {
                KYLIN_COMMON_LOG(_LOGL_ERR,"getNetContrlRule ruleName:%s ",modName.toLocal8Bit().data());
                errCode=NETCT_PARM_MISMATCH;
               break;
           }
           KYLIN_COMMON_LOG(_LOGL_DEBUG,"getNetContrlRule insert modName:%s",pItemCfgInfo->itemName);
           value.insert(QString(pItemCfgInfo->itemName),data);
       }
       else
       {
           KYLIN_COMMON_LOG(_LOGL_ERR,"getNetContrlRule ruleName:%s",modName.toLocal8Bit().data());
           errCode=NETCT_PARM_MISMATCH;
           //TODO 需要自己加自定义数据转换 暂时没用到
           break;
       }
    }

    g_list_free(list);
    return ;
}

NetCtrlAdaptor* NetCtrlAdaptor::getNetContrlInstance()
{
    static NetCtrlAdaptor*mInstance=NULL;
    if (mInstance == NULL) {
        mInstance = new NetCtrlAdaptor();
    }
    return mInstance;
}

void NetCtrlAdaptor::clearBackMessage()
{
    mType=0;
    mMessage=QString("");
    mErrcode=0;
    return ;
}


int NetCtrlAdaptor::waitNetCtrlBackResult(unsigned long long timeOutMs,QString cmd)
{
    unsigned long long startTime=kylinGetSysRtime();
    while((kylinGetSysRtime()-startTime)<timeOutMs) {
        if(mType && mMessage==cmd) {
            return 0;
        }
        QThread::msleep(1);
    }

    KYLIN_COMMON_LOG(_LOGL_WARN,"wait back result time out:%lld ",timeOutMs);
    return -1;
}

int NetCtrlAdaptor::sendNetCtrLog(int errcode,int type,QString message)
{
    KYLIN_COMMON_LOG(_LOGL_INFO,"recv %d type:%d message:%s\n",errcode,type,message.toLocal8Bit().data());
    QString level;

 // type类型NETCONTROL_LOG_TYPE 预留拓展
 //域控日志收集平台需要level固定为error
   level=QString("error");
   struct T_NetCtrlLogInfo *pNetCtrlLogInfo=( struct T_NetCtrlLogInfo *)malloc(sizeof(struct T_NetCtrlLogInfo));
   pNetCtrlLogInfo->level=g_strdup(level.toLocal8Bit().data());
   pNetCtrlLogInfo->messag=g_strdup(message.toLocal8Bit().data());
   kylinAsyncTaskAdd(mAsyncHandle,netCtrlAsyncSendHedronLog,pNetCtrlLogInfo);//qt有其他实现，此处使用自研代码实现，为后面迭代

   return 0;
}

void NetCtrlAdaptor::sendSysProxyNetCtlLog(QString message)
{
    struct T_NetCtrlLogInfo *pNetCtrlLogInfo=( struct T_NetCtrlLogInfo *)malloc(sizeof(struct T_NetCtrlLogInfo));
    pNetCtrlLogInfo->level=g_strdup(QString("error").toLocal8Bit().data());//域控日志收集平台需要level固定为error
    pNetCtrlLogInfo->messag=g_strdup(message.toLocal8Bit().data());

    kylinAsyncTaskAdd(mAsyncHandle,netCtrlAsyncSendHedronLog,pNetCtrlLogInfo);//qt有其他实现，此处使用自研代码实现，为后面迭代
}

void NetCtrlAdaptor::showDesktopNotify(const QString &message, QString soundName)
{
    QDBusInterface iface("org.freedesktop.Notifications",
                         "/org/freedesktop/Notifications",
                         "org.freedesktop.Notifications",
                         QDBusConnection::sessionBus());
    QStringList actions;  //跳转动作
    actions.append("default");
    actions.append("kylin-nm");          //默认动作：点击消息体时打开麒麟录音
    QMap<QString, QVariant> hints;
    if (!soundName.isEmpty()) {
        hints.insert("sound-name",soundName); //添加声音
    }
    QList<QVariant> args;
    args<<(tr("Kylin NM"))
       <<((unsigned int) 0)
       <<QString("gnome-dev-ethernet")
       <<tr("kylin network applet desktop message") //显示的是什么类型的信息
       <<message //显示的具体信息
       <<actions
       <<hints
       <<(int)-1;
    iface.callWithArgumentList(QDBus::AutoDetect,"Notify",args);
}
