#include "NonConnectedCameraHandle.h"
#include "mainwindow.h"

NonConnectedCameraHandle* NonConnectedCameraHandle::m_instance = nullptr;  // 初始化指针为空

NonConnectedCameraHandle::NonConnectedCameraHandle()
{
}

NonConnectedCameraHandle::~NonConnectedCameraHandle()
{
}

NonConnectedCameraHandle* NonConnectedCameraHandle::getInstance()
{
    if (m_instance == nullptr)  // 检查指针是否为空
    {
        m_instance = new NonConnectedCameraHandle();  // 创建新的实例并指向它
    }
    
    return m_instance;  // 返回指向实例的指针
}

bool NonConnectedCameraHandle::changeCameraIp(vides_data::localDevice &device){
    
    Common & instace= Common::getInstance();

    char interface[IFNAMSIZ];

    // 确定当前网络接口
    instace.determine_interface(interface);

    QString subnetMask;

    bool sub=vides_data::GetSubnetMask(subnetMask);
    QString gateway= instace.GetLocalGateWay();


    if ( !sub && gateway.length()==0 ) {
        qInfo() <<QString("SN(%1): 获取本地MAC失败").arg(device.sSn);
        return false ;
    }

    QByteArray && byJsonIp = device.reachableIp.toUtf8();
    const char * charIp= byJsonIp.data();
    
    signed char newEncryptPsw[512] = { 0 };
    int nMaxCount = 100;
    SXSDK_CONFIG_NET_COMMON* pRet = new SXSDK_CONFIG_NET_COMMON[nMaxCount];
    SXSDK_CONFIG_NET_COMMON* pDevice = nullptr;
    
    ScopeSemaphoreExit guard([&pRet]() {
        delete [] pRet;
    });
    memset(pRet, 0, sizeof(SXSDK_CONFIG_NET_COMMON) * nMaxCount);
    int nCount = XSDK_SearchDevicesSyn(pRet, nMaxCount);
    
    if (nCount <= 0) {
        qInfo() << QString("SN(%1): 有线搜索不到设备").arg(device.sSn);
        //搜索不到设备也当不在,当不在同一网段
        device.isMask=false;
        return false;
    }
    
    for (int i = 0; i < nCount; i++) {
        qInfo() << QString("[%1][IP:%2.%3.%4.%5][SN:%6][Mac:%7]")
                   .arg(i)
                   .arg(pRet[i].HostIP.c[0])
                .arg(pRet[i].HostIP.c[1])
                .arg(pRet[i].HostIP.c[2])
                .arg(pRet[i].HostIP.c[3])
                .arg(pRet[i].sSn)
                .arg(pRet[i].sMac);
        
        if (QString(pRet[i].sSn) == device.sSn) {
            pDevice = new SXSDK_CONFIG_NET_COMMON;
            memset(pDevice, 0, sizeof(SXSDK_CONFIG_NET_COMMON));
            memcpy(pDevice, &pRet[i], sizeof(SXSDK_CONFIG_NET_COMMON));
            break;
        }
    }
    
    if (pDevice == nullptr) {
        qInfo() << QString("SN(%1): 有线未找到匹配的设备").arg(device.sSn);
    } else {
        // 处理找到的设备信息
        qInfo() << QString("有线找到匹配的设备: SN(%1) IP:%2.%3.%4.%5 Mac:%6")
                   .arg(pDevice->sSn)
                   .arg(pDevice->HostIP.c[0])
                .arg(pDevice->HostIP.c[1])
                .arg(pDevice->HostIP.c[2])
                .arg(pDevice->HostIP.c[3])
                .arg(pDevice->sMac);
        
        // 在这里进行设备IP地址的更改操作
        
        SXSDK_CONFIG_NET_COMMON_V2 devInfo;
        memset(&devInfo, 0, sizeof(SXSDK_CONFIG_NET_COMMON_V2));
        
        QString  new_ip=QString("%1.%2.%3.%4")
                .arg(pDevice->HostIP.c[0])
                .arg(pDevice->HostIP.c[1])
                .arg(pDevice->HostIP.c[2])
                .arg(pDevice->HostIP.c[3]);
        QString  new_Submask=QString("%1.%2.%3.%4")
                .arg(pDevice->Submask.c[0])
                .arg(pDevice->Submask.c[1])
                .arg(pDevice->Submask.c[2])
                .arg(pDevice->Submask.c[3]);
        
        if(vides_data::isInSameSubnet(device.reachableIp,new_ip,new_Submask)){
            device.isMask=true;
        }else{
            device.isMask=false;
        }
        
        device.nDevPort=pDevice->TCPPort;
        XSDK_EncryptPassword("", newEncryptPsw, 512);
        
        device.UserName=  QString::fromUtf8(pDevice->DefaultUser,sizeof(pDevice->DefaultUser));
        device.password=  QString::fromUtf8(pDevice->DefaultPwd,sizeof(pDevice->DefaultPwd));
        
        devInfo.HostIP.l= inet_addr(charIp);
        devInfo.Gateway.l = inet_addr(gateway.toStdString().c_str());
        
        devInfo.Submask.l = inet_addr(subnetMask.toStdString().c_str());
        
        strcpy(devInfo.HostName, pDevice->HostName);
        devInfo.HttpPort = pDevice->HttpPort;
        //strcpy(devInfo.LocalMac, pDevice);
        devInfo.MaxBps = pDevice->MaxBps;
        devInfo.MaxConn = pDevice->MaxConn;
        devInfo.MonMode = pDevice->MonMode;
        devInfo.nPasswordType = 1;
        strcpy(devInfo.sMac, pDevice->sMac);
        strcpy(devInfo.Password, (const char*)newEncryptPsw);
        devInfo.SSLPort = pDevice->SSLPort;
        devInfo.TCPPort = pDevice->TCPPort;
        devInfo.TransferPlan = pDevice->TransferPlan;
        devInfo.UDPPort = pDevice->UDPPort;
        strcpy(devInfo.UserName, pDevice->DefaultUser);
        int nRet = XSDK_ModifyDevIP((const char*)&devInfo, sizeof(SXSDK_CONFIG_NET_COMMON_V2), 10000);
        delete pDevice;
        
        if(nRet<0){
            qInfo()<<QString("SN(%1): 有线修复ip失败错误码:%2").arg(device.sSn).arg(nRet);
            return false;
        }
    }
    return true;
    
}
bool NonConnectedCameraHandle::wifiChangeIp(QString &Ip, bool is_connect,
                                            int h_device,QString &sSn){
    Common & instace= Common::getInstance();
    
    XSDK_CFG::NetWork_Wifi wif;
    printWifi(h_device,wif);
    if(is_connect){
        if(!isWifiConnect(h_device,wif)){
            qInfo()<<QString("SN(%1): 不是wifi连接").arg(sSn);
            return  false;
        }
    }
    QString hex=instace.DecIpToHexIp(Ip);
    
    QByteArray && byIp = hex.toUtf8();
    const char * cpIp= byIp.data();
    wif.HostIP.SetValue(cpIp);
    wif.Enable.SetValue(true);
    wif.KeyType.SetValue(1);
    wif.EncrypType.SetValue("AES");
    wif.Auth.SetValue("WPA2PSK");
    
    const char* wipCfg = wif.ToString();
    char szOutBuffer[512] = { 0 };
    int nLen = sizeof(szOutBuffer);
    int res =XSDK_DevSetSysConfigSyn(h_device, JK_NetWork_Wifi, wipCfg, strlen(wipCfg), szOutBuffer, &nLen, 3000, EXCMD_CONFIG_SET);
    if(res<0){
        qInfo()<<QString("SN(%1): 无线修改wifi失败:%2").arg(sSn).arg(res);
        return  false;
    }
    return true;
}
bool NonConnectedCameraHandle::isWifiConnect(XSDK_HANDLE hDevice,XSDK_CFG::NetWork_Wifi &cfg){
    char szOutBuffer[4000] = { 0 };
    int  nInOutSize = sizeof(szOutBuffer);
    
    // 获取并解析配置
    int nResult = XSDK_DevGetSysConfigSyn(hDevice, JK_NetWork_Wifi, szOutBuffer, &nInOutSize, 3000, EXCMD_CONFIG_GET);
    qInfo()<<szOutBuffer;
    
    if (nResult >= 0) {
        cfg.Parse(szOutBuffer);
        return  strlen(cfg.SSID.Value())>0;
    } else {
        printf("Failed to get Wi-Fi configuration. Error code: %d\n", nResult);
        return  false;
    }
}

void NonConnectedCameraHandle::printWifi(XSDK_HANDLE hDevice,XSDK_CFG::NetWork_Wifi &cfg){
    char szOutBuffer[4000] = { 0 };
    int  nInOutSize = sizeof(szOutBuffer);
    
    // 获取并解析配置
    int nResult = XSDK_DevGetSysConfigSyn(hDevice, JK_NetWork_Wifi, szOutBuffer, &nInOutSize, 3000, EXCMD_CONFIG_GET);
    qInfo()<<szOutBuffer;
    
    if (nResult >= 0) {
        cfg.Parse(szOutBuffer);
    } else {
        printf("Failed to get Wi-Fi configuration. Error code: %d\n", nResult);
    }
}

int NonConnectedCameraHandle::sdkDevLoginSyn(QString sDevId, int nDevPort,
                                             QString sUserName, QString sPassword, int nTimeout) {
    SXSDKLoginParam *loginParam=new SXSDKLoginParam();
    ScopeSemaphoreExit guard([&loginParam]() {
        Common & instace= Common::getInstance();
        MainWindow::sp_this->setIsResetting(false);
        instace.deleteObj(loginParam);
    });
    QByteArray byteArray = sDevId.toUtf8();
    char* cDevid=byteArray.data();
    
    strcpy(loginParam->sDevId, cDevid);
    
    loginParam->nDevPort=nDevPort;
    
    QByteArray byteName = sUserName.toUtf8();
    char* cName=byteName.data();
    
    strcpy(loginParam->sUserName, cName);
    
    if(sPassword.length()>0){
        QByteArray bytePassword = sPassword.toUtf8();
        strcpy(loginParam->sPassword, bytePassword.constData());
    }else{
        strcpy(loginParam->sPassword, "");
    }
    loginParam->nCnnType=EDEV_CNN_TYPE_AUTO;
    int loginResult =XSDK_DevLoginSyn(loginParam,nTimeout);
    if(loginResult<0){
        qInfo() << QString("SN(%1): 登录设备失败").arg("NonConnectedCameraHandle");;
        return loginResult;
    }
    return loginResult;
}
bool NonConnectedCameraHandle::distributionNetwork(QString &ip,QString &sSn,int hDevice ){
    Common & instace= Common::getInstance();

    if(ip.length()>0  && instace.pingAddress(ip)){
        qInfo()<<QString("SN(%1): 当前ip已被使用%2").arg(sSn).arg(ip);
        return false;
    }
    int old=hDevice;
    
    MainWindow::sp_this->setIsResetting(true);
    ScopeSemaphoreExit guard([]() {
        MainWindow::sp_this->setIsResetting(false);
    });
    vides_data::localDevice device;
    QString reachableIp;
    if(ip.length()>0){
        reachableIp=ip;
        qInfo()<<QString("SN(%1): reachableIpIP地址%2").arg(sSn).arg(ip);
        qInfo()<<QString("SN(%1): IP地址%2").arg(sSn).arg(reachableIp);
        
    }else {
        reachableIp= vides_data::findReachableIp();
        if (!reachableIp.isEmpty()) {
            qInfo()<<QString("SN(%1): 未使用的IP地址%2").arg(sSn).arg(reachableIp);
        } else {
            qInfo()<<QString("SN(%1): 找不到可使用的IP地址").arg(sSn);
            return false ;
        }
    }
    device.reachableIp=reachableIp;
    device.sSn=sSn;
    device.isMask=true;
    //不在同一网段，改ip不成功则失败
    //在同一网段，改IP不成功则登录后尝试改wif'
    bool result= changeCameraIp(device);
    if(!result ){
        if(!device.isMask ){
            return false;
        }else {
            if(old<0){
                old=sdkDevLoginSyn(reachableIp,device.nDevPort,device.UserName,device.password,3000);
                if(old<0){
                    qInfo()<<QString("SN(%1): WIFI修改IP，新生成句柄失败").arg(sSn);
                }else {
                    result=wifiChangeIp(reachableIp,false,old,sSn);
                }
            }else {
                qInfo()<<QString("newIP(%1): wifiChangeIp").arg(reachableIp);
                result=wifiChangeIp(reachableIp,false,old,sSn);
                XSDK_DevLogout(old);
            }
        }
    }
    return result;
}
