#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <gsl/gl_mutex.h>
#include "al_basictypes.h"
#include "al_network_ctrl.h"
#include "netsetting_if.h"


typedef struct _Al_APList_t{
    al_int32 totalNum;
    Al_APInfo_t *pAPList;
}Al_APList_t;

static GL_Mutex_t stALAPListMutex;

static e_AL_Network_Mode stmode = 0;
static e_AL_IPMode       stIPMode = e_AL_IPMode_Auto;
static Al_APList_t st_APList = {.totalNum = 0, .pAPList = NULL};
static Al_APInfo_t st_selAP ;
static al_bool bInit = FALSE;

AL_Return_t _Al_Network_Ctrl_GetAPList(al_void)
{
    MID_NWSI_WLANINFO_t *pMidAPList = NULL;
    al_int32 idx;
    Al_APInfo_t *pAPInfo = NULL;


    pMidAPList = MID_NWSI_WLAN_GetAPList();
#if 0    
    printf("%s,%d - show ap list start \n", __FUNCTION__, __LINE__);
    if(pMidAPList)
    {
        for(idx=0; idx < pMidAPList->APTotalNum; idx++)
        {
            printf("data - name =%s, channl = %d, quality = %d, encryption = 0x%08x, mac =[%02x:%02x:%02x:%02x:%02x:%02x]\n",
                    pMidAPList->apdatalist[idx].APName,    pMidAPList->apdatalist[idx].APChannel, 
                    pMidAPList->apdatalist[idx].APQuality, pMidAPList->apdatalist[idx].APEncryption, 
                    pMidAPList->apdatalist[idx].APMAC.A,   pMidAPList->apdatalist[idx].APMAC.B,
                    pMidAPList->apdatalist[idx].APMAC.C,   pMidAPList->apdatalist[idx].APMAC.D, 
                    pMidAPList->apdatalist[idx].APMAC.E,   pMidAPList->apdatalist[idx].APMAC.F);
        }

    }
    printf("%s,%d - show ap list end\n",__FUNCTION__, __LINE__);
#endif    

    GL_MutexLock(stALAPListMutex);
    if(st_APList.pAPList) //free old memory
    {
        free(st_APList.pAPList);
        st_APList.pAPList = NULL;
        st_APList.totalNum = 0;
    }


     if(pMidAPList && (pMidAPList->APTotalNum != 0))
     {
         pAPInfo = (Al_APInfo_t *)malloc(sizeof(Al_APInfo_t) * pMidAPList->APTotalNum);
         if(!pAPInfo)
           goto _exit_;

         memset(pAPInfo, 0, sizeof(Al_APInfo_t) * pMidAPList->APTotalNum );

        for(idx =0; idx < pMidAPList->APTotalNum; idx++)
        {
            memcpy(pAPInfo[idx].name, pMidAPList->apdatalist[idx].APName, 33);
            pAPInfo[idx].channel = pMidAPList->apdatalist[idx].APChannel;
            pAPInfo[idx].quality = pMidAPList->apdatalist[idx].APQuality;
            pAPInfo[idx].encryption= pMidAPList->apdatalist[idx].APEncryption;
            pAPInfo[idx].mac.MACA = pMidAPList->apdatalist[idx].APMAC.A;
            pAPInfo[idx].mac.MACB = pMidAPList->apdatalist[idx].APMAC.B;
            pAPInfo[idx].mac.MACC = pMidAPList->apdatalist[idx].APMAC.C;
            pAPInfo[idx].mac.MACD = pMidAPList->apdatalist[idx].APMAC.D;
            pAPInfo[idx].mac.MACE = pMidAPList->apdatalist[idx].APMAC.E;
            pAPInfo[idx].mac.MACF = pMidAPList->apdatalist[idx].APMAC.F;
        }
        st_APList.pAPList = pAPInfo;
        st_APList.totalNum = pMidAPList->APTotalNum;
     }
#if 0
    printf("%s,%d - show copy ap list start \n", __FUNCTION__, __LINE__);
    if(st_APList.pAPList)
    {
        for(idx=0; idx < st_APList.totalNum; idx++)
        {
            printf("data - name =%s, channl = %d, quality = %d, encryption = 0x%08x, mac =[%02x:%02x:%02x:%02x:%02x:%02x]\n",
                    st_APList.pAPList[idx].name,    st_APList.pAPList[idx].channel, 
                    st_APList.pAPList[idx].quality, st_APList.pAPList[idx].encryption, 
                    st_APList.pAPList[idx].mac.MACA,   st_APList.pAPList[idx].mac.MACB,
                    st_APList.pAPList[idx].mac.MACC,   st_APList.pAPList[idx].mac.MACD, 
                    st_APList.pAPList[idx].mac.MACE,   st_APList.pAPList[idx].mac.MACF);
        }

    }
    printf("%s,%d - show copy ap list end\n",__FUNCTION__, __LINE__);
 #endif   

 _exit_:
    GL_MutexUnlock(stALAPListMutex);
    if(pMidAPList)
    {
        if(pMidAPList->apdatalist)
            free(pMidAPList->apdatalist);
        free(pMidAPList);
    } 
 
    return AL_SUCCESS;
}

al_int32 _Al_Network_Ctrl_CallBack(E_MID_NWSI_REPORT_TYPE type,al_void *pParam)
{
    switch(type)
    {
        case E_MID_NWSI_REPORT_WLAN_AP_ScanStart:
            printf("%s - E_MID_NWSI_REPORT_WLAN_AP_ScanStart\n", __FUNCTION__);
            break;
        case E_MID_NWSI_REPORT_WLAN_AP_ScanStop:
            printf("%s - E_MID_NWSI_REPORT_WLAN_AP_ScanStop\n", __FUNCTION__);
            break;
        case E_MID_NWSI_REPORT_WLAN_AP_ListUpdate:
            printf("%s - E_MID_NWSI_REPORT_WLAN_AP_ListUpdate\n", __FUNCTION__);
            _Al_Network_Ctrl_GetAPList();
            break;
        case E_MID_NWSI_REPORT_WLAN_DEVICE_DISABLED:
            printf("%s - E_MID_NWSI_REPORT_WLAN_DEVICE_DISABLED\n", __FUNCTION__);
            break;
        case E_MID_NWSI_REPORT_WLAN_DEVICE_ENABLED:
            printf("%s - E_MID_NWSI_REPORT_WLAN_DEVICE_ENABLED\n", __FUNCTION__);
            break;
        default:
            printf("%s - \n", __FUNCTION__);
            break;

    }

    return 1;
}

AL_Return_t Al_Network_Ctrl_Init(al_void)
{
    GL_Status_t dReturnValue;
    AL_Return_t alret = AL_SUCCESS;
	
	if(bInit)
		return alret;
    MID_NWSI_Init();
    MID_NWSI_RegisterCB(_Al_Network_Ctrl_CallBack);

    dReturnValue = GL_MutexCreate("wlan_apscan_mutex", &stALAPListMutex);
    if(dReturnValue != GL_SUCCESS)
    {
        printf("create al_aplist mutex failed\n");    
        alret = AL_FAILURE;
    }
    return alret;
}

AL_Return_t Al_Network_Ctrl_Destroy(al_void)
{
    MID_NWSI_UnRegisterCB();
    MID_NWSI_Destory();

    if(st_APList.pAPList) //free old memory
    {
        free(st_APList.pAPList);
        st_APList.pAPList = NULL;
        st_APList.totalNum = 0;
     }
    GL_MutexDelete(stALAPListMutex);
    stALAPListMutex = 0;
    return AL_SUCCESS;
}   

al_void Al_Network_Ctrl_Set_ConnectMode(e_AL_Network_Mode mode)
{
	if(stmode==mode)
		return;
	
    if(e_AL_Network_Mode_Wireless == mode)
    {//set wireless mode

        MID_NWSI_DisableConnectMode();
        MID_NWSI_SetConnectMode(E_MID_NWSI_CONNECT_TYPE_WIRELESS);
        MID_NWSI_EnableConnectMode();
    }
    else if(e_AL_Network_Mode_Ethernet == mode)
    {

        MID_NWSI_DisableConnectMode();
        MID_NWSI_SetConnectMode(E_MID_NWSI_CONNECT_TYPE_ETHERNET);
        MID_NWSI_EnableConnectMode();
    }
    else
    {
        MID_NWSI_DisableConnectMode();    
        MID_NWSI_SetConnectMode(E_MID_NWSI_CONNECT_TYPE_END);
    }

    stmode = mode;    
}

al_int32 Al_Network_Ctrl_GetAPNum(al_void)
{
   al_int32 num = 0;
   MID_NWSI_WLAN_ScanAP();
   GL_MutexLock(stALAPListMutex);
   num = st_APList.totalNum;
   GL_MutexUnlock(stALAPListMutex);
    return num;
}


al_int32 Al_Network_Ctrl_QueryAPData(al_int32 from, al_int32 numAP, Al_APInfo_t *pAPInfo)
{
    al_int32 copyTotal = 0, idx=0;


    if(!pAPInfo)
        return 0;
    
    if( (from < 0) || (numAP <= 0))
        return 0;
    
    GL_MutexLock(stALAPListMutex);
    if(from >= st_APList.totalNum)
           goto _exit_;
    
    copyTotal = ((from + numAP) <= st_APList.totalNum) ? numAP : (st_APList.totalNum - from) ;
    
    for(idx = 0; idx < copyTotal; ++idx)
    {
        memcpy(&pAPInfo[idx], &st_APList.pAPList[from + idx], sizeof(Al_APInfo_t));
    }

_exit_:        
    GL_MutexUnlock(stALAPListMutex);
    return copyTotal;

}

AL_Return_t Al_Network_Ctrl_SetIP(Al_IP_t *pIP)
{
    MID_NWSI_IPv4_Addr_t ip; 
    al_int32 ret;
    if(!pIP)
        return AL_FAILURE;

    ip.A = pIP->IPA;
    ip.B = pIP->IPB;
    ip.C = pIP->IPC;
    ip.D = pIP->IPD;
    ret = MID_NWSI_SetIP(stmode, ip);

    return (ret == S_OK) ? AL_SUCCESS : AL_FAILURE;
}

AL_Return_t Al_Network_Ctrl_SetNetMask(Al_NetMask_t *pNetMask)
{
    MID_NWSI_IPv4_Addr_t netmask; 
    al_int32 ret;
    if(!pNetMask)
        return AL_FAILURE;

    netmask.A = pNetMask->MaskA;
    netmask.B = pNetMask->MaskB;
    netmask.C = pNetMask->MaskC;
    netmask.D = pNetMask->MaskD;
    ret = MID_NWSI_SetNetmask(stmode, netmask);

    return (ret == S_OK) ? AL_SUCCESS : AL_FAILURE;

}
AL_Return_t Al_Network_Ctrl_SetGateway(Al_Gateway_t *pGateWay)
{
    MID_NWSI_IPv4_Addr_t gateway; 
    al_int32 ret;
    if(!pGateWay)
        return AL_FAILURE;

    gateway.A = pGateWay->GwA;
    gateway.B = pGateWay->GwB;
    gateway.C = pGateWay->GwC;
    gateway.D = pGateWay->GwD;
    ret = MID_NWSI_SetGateway(stmode, gateway);

    return (ret == S_OK) ? AL_SUCCESS : AL_FAILURE;

}

AL_Return_t Al_Network_Ctrl_SetDNS(Al_DNS_t *pDNS1,Al_DNS_t *pDNS2)
{
    MID_NWSI_IPv4_Addr_t dns1, dns2; 
    al_int32 ret;

    if(!pDNS1 && !pDNS2)
        return AL_FAILURE;

    memset(&dns1, 0, sizeof(MID_NWSI_IPv4_Addr_t));
    memset(&dns2, 0, sizeof(MID_NWSI_IPv4_Addr_t));

    if(pDNS1)
    {
        dns1.A = pDNS1->DNSA;
        dns1.B = pDNS1->DNSB;
        dns1.C = pDNS1->DNSC;
        dns1.D = pDNS1->DNSD;
    }
    if(pDNS2)
    {
        dns2.A = pDNS2->DNSA;
        dns2.B = pDNS2->DNSB;
        dns2.C = pDNS2->DNSC;
        dns2.D = pDNS2->DNSD;

    }

    ret = MID_NWSI_SetDNS(dns1,dns2);

    return (ret == S_OK) ? AL_SUCCESS : AL_FAILURE;
}

AL_Return_t Al_Network_Ctrl_GetIP(Al_IP_t *pIP)
{
    MID_NWSI_IPv4_Addr_t ip; 
    al_int32 ret;

    if(!pIP)
        return AL_FAILURE;

    if(MID_NWSI_GetConnectMode() == E_MID_NWSI_CONNECT_TYPE_WIRELESS)
    {
    	if(MID_NWSI_WLAN_GetAPState() != E_MID_NWSI_WLAN_CONNECT_STATE_ON)
		return AL_FAILURE;
    }
        

    ret = MID_NWSI_GetIP(stmode, &ip);

    if(ret == S_OK)
    {
        pIP->IPA = ip.A;        
        pIP->IPB = ip.B;
        pIP->IPC = ip.C;
        pIP->IPD = ip.D;
    }

    return (ret == S_OK) ? AL_SUCCESS : AL_FAILURE;

}

AL_Return_t Al_Network_Ctrl_SetDhcpStatic(e_AL_Network_Mode cType, e_AL_IPMode ipType, Al_IPSET_t *pIPSet)
{
	al_int32 ret = AL_SUCCESS;
	
	if(ipType == e_AL_IPMode_Manual)
	{
		if(pIPSet != NULL)
		{
			stmode = cType;
			ret &= Al_Network_Ctrl_SetIP(&pIPSet->IP);
			ret &= Al_Network_Ctrl_SetNetMask(&pIPSet->NetMask);
			ret &= Al_Network_Ctrl_SetGateway(&pIPSet->GateWay);
			ret &= Al_Network_Ctrl_SetDNS(&pIPSet->DNS1,&pIPSet->DNS2);
		}
		else
			ret &= AL_FAILURE;
	}
	else
	{
		ret &= ((MID_NWSI_SetDHCP(cType)==E_FAIL)? AL_FAILURE: AL_SUCCESS);
	}

	return ret;
}

AL_Return_t Al_Network_Ctrl_GetNetMask(Al_NetMask_t *pNetMask)
{

    MID_NWSI_IPv4_Addr_t netmask; 
    al_int32 ret;

    if(!pNetMask)
        return AL_FAILURE;

    ret = MID_NWSI_GetNetmask(stmode, &netmask);

    if(ret == S_OK)
    {
        pNetMask->MaskA= netmask.A;        
        pNetMask->MaskB= netmask.B;
        pNetMask->MaskC= netmask.C;
        pNetMask->MaskD= netmask.D;
    }

    return (ret == S_OK) ? AL_SUCCESS : AL_FAILURE;

}

AL_Return_t Al_Network_Ctrl_GetGateway(Al_Gateway_t *pGateWay)
{
    MID_NWSI_IPv4_Addr_t gateway; 
    al_int32 ret;

    if(!pGateWay)
        return AL_FAILURE;

    ret = MID_NWSI_GetGateway(stmode, &gateway);

    if(ret == S_OK)
    {
        pGateWay->GwA= gateway.A;        
        pGateWay->GwB= gateway.B;
        pGateWay->GwC= gateway.C;
        pGateWay->GwD= gateway.D;
    }

    return (ret == S_OK) ? AL_SUCCESS : AL_FAILURE;

}

AL_Return_t Al_Network_Ctrl_GetMAC(Al_MAC_t *pMac)
{
    MID_NWSI_MAC_Addr_t mac;
    al_int32 ret;
    

    if(!pMac)
        return AL_FAILURE;

    ret = MID_NWSI_GetMAC(stmode, &mac);
    if(ret == S_OK)
    {
         pMac->MACA = mac.A;
         pMac->MACB = mac.B;
         pMac->MACC = mac.C;
         pMac->MACD = mac.D;
         pMac->MACE = mac.E;
         pMac->MACF = mac.F;
    }


    return (ret == S_OK) ? AL_SUCCESS : AL_FAILURE;
}

AL_Return_t Al_Network_Ctrl_GetDNS(Al_DNS_t *pDNS1, Al_DNS_t *pDNS2)
{
    MID_NWSI_IPv4_Addr_t dns1, dns2; 
    al_int32 ret;

    if(!pDNS1&& !pDNS2)
        return AL_FAILURE;    

    ret = MID_NWSI_GetDNS(&dns1, &dns2);
    if(ret == S_OK)
    {
        if(pDNS1)
        {
            pDNS1->DNSA = dns1.A;
            pDNS1->DNSB = dns1.B;
            pDNS1->DNSC = dns1.C;
            pDNS1->DNSD = dns1.D;
        }
        if(pDNS2)
        {
            pDNS2->DNSA = dns2.A;
            pDNS2->DNSB = dns2.B;
            pDNS2->DNSC = dns2.C;
            pDNS2->DNSD = dns2.D;

        }
    }


    return (ret == S_OK) ? AL_SUCCESS : AL_FAILURE;

}

al_int32 Al_Network_Ctrl_GetMTU(al_void)
{
    al_int32 mtu;

    mtu = MID_NWSI_GetMTU(stmode);

    return mtu;
}

al_void Al_Network_Ctrl_SetIPMode(e_AL_IPMode IPMode)
{
    stIPMode = IPMode;
}


AL_Return_t Al_Network_Ctrl_ConnectAP(Al_APInfo_t APInfo, al_uint8 keylen, al_int8 pKey[])
{

    MID_NWSI_APData_t ap;
    al_int32 ret = 0;
    al_uint8 apstate = E_MID_NWSI_WLAN_CONNECT_STATE_OFF;

    apstate = MID_NWSI_WLAN_GetAPState();
    printf("apstate = %d\n", apstate);

    if(apstate == E_MID_NWSI_WLAN_CONNECT_STATE_ON)
    {
        return AL_SUCCESS;
    }

    memset(&st_selAP, 0, sizeof(Al_APInfo_t)); //reset select ap 
    memset(&ap, 0, sizeof(MID_NWSI_APData_t));

    memcpy(ap.APName, APInfo.name, sizeof(APInfo.name));
    ap.APChannel = APInfo.channel;
    ap.APQuality = APInfo.quality;
    ap.APEncryption = APInfo.encryption;
    ap.APMAC.A = APInfo.mac.MACA;
    ap.APMAC.B = APInfo.mac.MACB;
    ap.APMAC.C = APInfo.mac.MACC;
    ap.APMAC.D = APInfo.mac.MACD;
    ap.APMAC.E = APInfo.mac.MACE;
    ap.APMAC.F = APInfo.mac.MACF;
    ret = MID_NWSI_WLAN_ConnectSelectedAP(&ap, keylen, pKey);

    if(S_OK == ret)
       apstate = MID_NWSI_WLAN_GetAPState();
    printf("apstate = %d\n", apstate);

    if(apstate == E_MID_NWSI_WLAN_CONNECT_STATE_ON)
    {
        memcpy(&st_selAP, &APInfo, sizeof(Al_APInfo_t));

    }

    return (apstate  == E_MID_NWSI_WLAN_CONNECT_STATE_ON) ? AL_SUCCESS :  AL_FAILURE;
            
}

AL_Return_t Al_Network_Ctrl_DisconnectAP(void)
{
    MID_NWSI_WLAN_Disconnect();
    
    return AL_SUCCESS;
}

al_bool AL_Network_Ctrl_GetConnectStatus()
{
	if(MID_NWSI_IFStatus())
	{
		return TRUE;
	}
	 return FALSE;
}

al_bool Al_Network_Ctrl_GetConnectAPData(Al_APInfo_t *pConnectedAPInfo)
{
	if(pConnectedAPInfo!=NULL)
	{
		if(MID_NWSI_WLAN_GetAPState()==E_MID_NWSI_WLAN_CONNECT_STATE_ON)
		{
			memcpy(pConnectedAPInfo, &st_selAP, sizeof(Al_APInfo_t));
			return TRUE;
		}
	}
	return FALSE;
}

AL_Return_t Al_Network_Ctrl_CheckWireless(void)
{
    MID_NWSI_MAC_Addr_t mac;
    al_int32 ret;

    ret = MID_NWSI_GetMAC(e_AL_Network_Mode_Wireless, &mac);

    return (ret == S_OK) ? AL_SUCCESS : AL_FAILURE;
}

al_int8 Al_Network_Ctrl_GetAPQuailty(void)
{
   al_int8 quality = 0;
   al_int32 idx;
   MID_NWSI_WLAN_ScanAP();
   GL_MutexLock(stALAPListMutex);
   for(idx =0; idx < st_APList.totalNum; idx++)
   {
	   if(strcmp(st_APList.pAPList[idx].name, st_selAP.name) == 0)
	   	quality=st_APList.pAPList[idx].quality;
   }
   GL_MutexUnlock(stALAPListMutex);
    return quality;
}

al_int8 Al_Network_Ctrl_GetP2PQuailty(void)
{
	al_int8 quality = 0;
	al_int32 idx;
	FILE *fptr=NULL;
	char line[100];
	char name[100];
	BOOL bUpdate = FALSE;
	
#if (defined CONFIG_SUPPORT_RTL8188) || (defined CONFIG_SUPPORT_RTL8188) || (defined CONFIG_SUPPORT_RTL8723BU) || (defined CONFIG_SUPPORT_RTL8723DU)
	bUpdate = MID_NWSI_P2P_ScanAP(E_MID_NWSI_INTERFACE_WLAN1);
#elif defined(CONFIG_SUPPORT_NORMAL_MTK7601) || defined(CONFIG_SUPPORT_RDA5995)
	bUpdate = MID_NWSI_P2P_ScanAP(E_MID_NWSI_INTERFACE_P2P0);
#endif
	fptr = fopen("/tmp/wfa.action.SSID", "rb");
	if(fptr != NULL)
	{
		memset(line, 0, 100);
		memset(name, 0, 100);
		fgets(line, 100, fptr);
		if(line[strlen(line)-1] == '\n')
			line[strlen(line)-1] = '\0';
		strcpy(name, strchr(line, '=')+1);
		fclose(fptr);
	}
	if(bUpdate)
		_Al_Network_Ctrl_GetAPList();
	GL_MutexLock(stALAPListMutex);
	for(idx =0; idx < st_APList.totalNum; idx++)
	{
		if(strcmp(st_APList.pAPList[idx].name, name) == 0)
			quality=st_APList.pAPList[idx].quality;
	}
	GL_MutexUnlock(stALAPListMutex);
	return quality;
}

