#include "netdev_om_lmb26.h"

#include "sr_osal.h"
#include "sr_log.h"
#include "at.h"

#include "nb/svc/svc_nb_core.h"


typedef struct _STACK
{
	//at_response_t resp; 
	uint16_t i;

}_STACK_T;


static int _Cfun0Cb(at_client_t client,at_response_t resp)
{

	AT_DEVICE_T *atDev = SR_CONTAINER_OF(client, AT_DEVICE_T, atClient);
	SR_NETDEV_T *netdev = atDev->netdev;
	NetdevEvtCb eventCb = (NetdevEvtCb)netdev->netEvtCb;

	//调用网卡运维事件回调
	if(eventCb) eventCb(netdev->netEvtArgs,SR_NET_EVT_CFUN,0,SR_CFUN_MODE_FLY);

	return 0;
}

static int _Cfun1Cb(at_client_t client,at_response_t resp)
{
	AT_DEVICE_T *atDev = SR_CONTAINER_OF(client, AT_DEVICE_T, atClient);
	SR_NETDEV_T *netdev = atDev->netdev;
	NetdevEvtCb eventCb = (NetdevEvtCb)netdev->netEvtCb;

	//调用网卡运维事件回调
	if(eventCb) eventCb(netdev->netEvtArgs,SR_NET_EVT_CFUN,0,SR_CFUN_MODE_FULL);

	return 0;
}

static int _CgattCb(at_client_t client,at_response_t resp)
{
	AT_DEVICE_T *atDev = SR_CONTAINER_OF(client, AT_DEVICE_T, atClient);
	SR_NETDEV_T *netdev = atDev->netdev;
	NetdevEvtCb eventCb = (NetdevEvtCb)netdev->netEvtCb;

	char *p;
	uint8_t attach;

	p = at_resp_get_line_by_kw(resp, "+CGATT:"); //查找关键字
	if (p==SR_NULL) {
		SR_LOG_DEBUG("not find cgatt");
		return -1;
	}

	SR_LOG_DEBUG("att: %s", p);

	//提取附着状态
	if(sscanf(p, "+CGATT: %d", &attach)==1)
	{
		if(attach!=1) 
		{
			SR_LOG_DEBUG("+CGATT: %d,!=1", attach);
			return -1;
		}

	} else {
		SR_LOG_DEBUG("sscanf cgatt error");
		return -1;
	}

	//调用网卡运维事件回调
	if(eventCb) eventCb(netdev->netEvtArgs,SR_NET_EVT_LINK,0,SR_NET_LINK_ON);

	return 0;
}



//网络初始化AT列表
static const AT_INIT_TABLE_T atInitTable[] = {
    {"AT\r\n",          SR_NULL,   3000,   5},
	{"AT+CFUN=0\r\n",   _Cfun0Cb , 8000,   3},
    {"AT+CMEE=1\r\n",   SR_NULL,   3000,   3},
    {"AT+CEREG=1\r\n",  SR_NULL,   3000,   3},
	{"AT+CSCON=0\r\n",  SR_NULL,   3000,   3},
	{"AT+CFUN=1\r\n",   _Cfun1Cb , 3000,   3},
    {"AT+CGATT?\r\n",   _CgattCb,  5000,  30},
};

//int SR_AtResendCmdwithCb(at_client_t client, at_response_t resp,int (*cb)(at_response_t resp), uint8_t resendCnt,const char *cmdExpr, ...);

int _Lmb26NetSwitch(SR_NETDEV_T *dev, uint8_t simId,SR_NET_SW_E opt)
{
	SR_GET_CT();
	_STACK_T *stack = (_STACK_T *)SR_ALLOC_STACK(ct,sizeof(_STACK_T));
	uint16_t cmdNum = sizeof(atInitTable)/sizeof(AT_INIT_TABLE_T);
	AT_DEVICE_T *atDev = (AT_DEVICE_T *)dev->atDev;

	int ret=SR_OK;


	SR_CT_BEGIN();

#if  0
	//1、创建响应结构体，设置最大支持响应数据长度为 512 字节，响应数据行数无限制，超时时间为 5 秒 
	stack->resp =  at_create_resp(512, 0, SR_OsMsToTick(5000));
	if (stack->resp == SR_NULL)
	{
		SR_LOG(ERR, "No memory for response structure!");
		SR_CT_RETURN(SR_NOMEM);  //返回
	}
#endif

	//获取互斥量
	SR_CT_MUTEX_TAKE(ct,&(atDev->atClient.lock), OS_WAIT_FOREVER);


	if(SR_NET_OPEN == opt)
	{
		// 2.1、NB网络使能，按网络初始化AT列表依次发送
		//while (pNbCore->cmd_index < pNbCore->cmd_num)
		for(stack->i=0; stack->i<cmdNum; stack->i++)
		{		
			// 串口打印发送内容
			SR_LOG(DEBUG, "send cmd:%s", atInitTable[stack->i].sendCmd);

			//发送AT命令，内部处理重发，并调用回调函数
			ret = SR_AtResendCmdwithCb(&atDev->atClient, atDev->resp, atInitTable[stack->i].cb,atInitTable[stack->i].timeout,atInitTable[stack->i].resendCnt, (const char *)atInitTable[stack->i].sendCmd);

			if(ret != SR_OK) break;
			
		}
			
	
	}
	else
	{
		// 2.2、NB网络失能，进入飞行

	}
	
	//释放互斥量
	SR_CT_MUTEX_RELEASE(&(atDev->atClient.lock));

	//3、释放响应结构体
	//at_delete_resp(stack->resp);

	//SR_CT_RETURN(ret);  //返回
	return ret;

	SR_CT_END();
}



#if   0
int _Lmb26GetImei(SR_NETDEV_T *dev, uint8_t simId, char *buf, srSize_t len)
{
  int ret = -1;

  // @return int <= 0错误 >0实际传出的大小
  ret = luat_mobile_get_imei(simId,buf,len);  //通常15字节

  return ret<=0?-1:ret;

}


int _Lmb26GetImsi(SR_NETDEV_T *dev, uint8_t simId, char *buf, srSize_t len)
{
  int ret = -1;

  
  // @return int <= 0错误 >0实际传出的大小
  ret = luat_mobile_get_imsi(simId,buf,len);  //通常15字节

  return ret<=0?-1:ret;

}


int _Lmb26GetIccid(SR_NETDEV_T *dev, uint8_t simId, char *buf, srSize_t len)
{
  int ret = -1;

  // @return int <= 0错误 >0实际传出的大小
  ret = luat_mobile_get_iccid(simId,buf,len);  //通常15字节

  return ret<=0?-1:ret;

}



int _Lmb26SetCfun(SR_NETDEV_T *dev, uint8_t simId, SR_CFUN_MODE_E cfunMode)
{  
    int ret = -1,mode = 0;

	  
    //飞行模式设置，对应  AT+CFUN=指令 0:开启飞行              1:关闭飞行
	//原厂SDK:mode 飞行模式，1进入，0退出 
	mode = (cfunMode==0)?1:0;  //这里取反

	//hz: return: int =0成功，其他失败; mode 飞行模式，1进入，0退出  
	ret = luat_mobile_set_flymode(simId,mode); 
	

	return ret==0? SR_OK:SR_FAIL;
}


int _Lmb26GetCfun(SR_NETDEV_T *dev, uint8_t simId, SR_CFUN_MODE_E *cfunMode)
{
  int ret  = SR_FAIL;
  int mode = -1;
  
  //rerurn int <0 异常 =0飞行模式 =1正常工作 =4射频关闭 
  mode = luat_mobile_get_flymode(simId);

  switch(mode)
  {
     case 0:
	 	*cfunMode = SR_CFUN_MODE_FLY;
		ret =0;
	 break;

	 case 1:
	 	*cfunMode = SR_CFUN_MODE_FULL;
		ret =0;
	 break;
	 default:
	 	*cfunMode = -1;
		break;
	
  }

  return ret; 
}





int _Lmb26GetCellInfo(SR_NETDEV_T *dev, uint8_t simId,SR_NET_CELL_INFO_T *cellInfo)
{
	int ret =-1;

	luat_mobile_cell_info_t  mobileCellInfo={0};


	//手动获取一次周围小区信息，同步方式

	//SDK return:int =0成功，其他失败 
	ret = luat_mobile_get_cell_info(&mobileCellInfo);

    if(ret) goto _END;


	if (mobileCellInfo.lte_service_info.cid)
	{
#if 0
	  BSP_DEBUG_PRINTF("服务小区信息 mcc %x mnc %x cellid %u band %d tac %u pci %u earfcn %u is_tdd %d rsrp %d rsrq %d snr %d rssi %d",
			  mobileCellInfo.lte_service_info.mcc, mobileCellInfo.lte_service_info.mnc, mobileCellInfo.lte_service_info.cid,
			  mobileCellInfo.lte_service_info.band, mobileCellInfo.lte_service_info.tac, mobileCellInfo.lte_service_info.pci, mobileCellInfo.lte_service_info.earfcn,
			  mobileCellInfo.lte_service_info.is_tdd, mobileCellInfo.lte_service_info.rsrp, mobileCellInfo.lte_service_info.rsrq,
			  mobileCellInfo.lte_service_info.snr, mobileCellInfo.lte_service_info.rssi);
#endif

		cellInfo->srvInfo.mcc = mobileCellInfo.lte_service_info.mcc;   
		cellInfo->srvInfo.mnc = mobileCellInfo.lte_service_info.mnc;   
		cellInfo->srvInfo.cid = mobileCellInfo.lte_service_info.cid;   			 
		cellInfo->srvInfo.tac = mobileCellInfo.lte_service_info.tac;   
		cellInfo->srvInfo.pci = mobileCellInfo.lte_service_info.pci;   
		cellInfo->srvInfo.earfcn = mobileCellInfo.lte_service_info.earfcn;
		cellInfo->srvInfo.rsrp = mobileCellInfo.lte_service_info.rsrp;  
		cellInfo->srvInfo.rsrq = mobileCellInfo.lte_service_info.rsrq;  
		cellInfo->srvInfo.snr = mobileCellInfo.lte_service_info.snr;   
		cellInfo->srvInfo.rssi = mobileCellInfo.lte_service_info.rssi; 
		cellInfo->srvInfo.band = mobileCellInfo.lte_service_info.band;
	  
	}
	else
	{
		memset(&cellInfo->srvInfo,0,sizeof(SR_CELL_INFO_T));
	}


	cellInfo->nbrInfoNum = mobileCellInfo.lte_neighbor_info_num;
	for (int i = 0; i < mobileCellInfo.lte_neighbor_info_num; i++)
	{
		if (mobileCellInfo.lte_info[i].cid)
		{

		    #if 0
			  BSP_DEBUG_PRINTF("邻小区 %d mcc %x mnc %x cellid %u tac %u pci %u", i + 1, mobileCellInfo.lte_info[i].mcc,
					  mobileCellInfo.lte_info[i].mnc, mobileCellInfo.lte_info[i].cid, mobileCellInfo.lte_info[i].tac, mobileCellInfo.lte_info[i].pci);
			  BSP_DEBUG_PRINTF("邻小区 %d earfcn %u rsrp %d rsrq %d snr %d", i + 1, mobileCellInfo.lte_info[i].earfcn, mobileCellInfo.lte_info[i].rsrp,
					  mobileCellInfo.lte_info[i].rsrq, mobileCellInfo.lte_info[i].snr);
		    #endif

			cellInfo->nbrInfo[i].mcc =  mobileCellInfo.lte_info[i].mcc;
			cellInfo->nbrInfo[i].mnc =  mobileCellInfo.lte_info[i].mnc; 
			cellInfo->nbrInfo[i].cid =  mobileCellInfo.lte_info[i].cid; 
			cellInfo->nbrInfo[i].tac =  mobileCellInfo.lte_info[i].tac;
			cellInfo->nbrInfo[i].pci =  mobileCellInfo.lte_info[i].pci;
			cellInfo->nbrInfo[i].earfcn = mobileCellInfo.lte_info[i].earfcn;
			cellInfo->nbrInfo[i].rsrp = mobileCellInfo.lte_info[i].rsrp;
			cellInfo->nbrInfo[i].rsrq = mobileCellInfo.lte_info[i].rsrq; 
			cellInfo->nbrInfo[i].snr =  mobileCellInfo.lte_info[i].snr;
			cellInfo->nbrInfo[i].rssi =  mobileCellInfo.lte_info[i].rssi;

		}
		else
		{
			memset(&cellInfo->nbrInfo[i],0,sizeof(SR_CELL_INFO_T));
		}
	}


_END:
	return (ret==0)? 0:-1;
}




int _Lmb26GetSignalStreng(SR_NETDEV_T *dev, uint8_t simId,SR_NET_SGN_STRENG_T *streng)
{

  	int ret =-1;

	luat_mobile_cell_info_t  mobileCellInfo={0};
    luat_mobile_signal_strength_info_t  mobileSignalInfo={0};

	//1、手动获取一次周围小区信息，同步方式
	//SDK return:int =0成功，其他失败 
	ret = luat_mobile_get_cell_info(&mobileCellInfo);   //先获取cell信息

	if(ret) goto _END;


	//2、获取最新的信号强度信息
	//SDK return:int =0成功，其他失败 
    ret =  luat_mobile_get_last_notify_signal_strength_info(&mobileSignalInfo);

	if(ret || !mobileSignalInfo.luat_mobile_lte_signal_strength_vaild) 
	{
      ret = SR_FAIL;
	  goto _END;
	}

    streng->rssi = mobileSignalInfo.lte_signal_strength.rssi;
	streng->rsrp = mobileSignalInfo.lte_signal_strength.rsrp;
	streng->rsrq = mobileSignalInfo.lte_signal_strength.rsrq;
	streng->snr  = mobileSignalInfo.lte_signal_strength.snr;		

_END:
	return ret;

}



int _Lmb26GetPdpSta(SR_NETDEV_T *dev, uint8_t simId,SR_PDP_STA_E *pdpSta)
{

   *pdpSta = dev->pdpSta;
   return 0;
}

int _Lmb26GetNetlinkSta(SR_NETDEV_T *dev, uint8_t simId,SR_NET_LINK_STA_E *linkSta)
{

   *linkSta = dev->linkSta;
   return 0;
}


//检查sim卡是否准备好          0:OK   -1:not ready
int _Lmb26CheckSimReady(SR_NETDEV_T *dev, uint8_t simId)
{
  int ret =0;
  // 原SDK 返回=1准备好，其他未准备好，或者SIM卡不在位 
  ret =  luat_mobile_get_sim_ready(simId);

  return ret==1?0:-1;

}



//获取网络注册状态
int _Lmb26GetNetRegSta(SR_NETDEV_T *dev, uint8_t simId,SR_NET_REG_STA_E *regSta)
{
   uint8_t status;
   status = luat_mobile_get_register_status();

   *regSta = status;
	if(status >= LUAT_MOBILE_STATUS_SMS_ONLY_REGISTERED) *regSta = 0xFF;	//无效值

   return 0;
}
#endif
