#include "xbuf.h"
#include "errno.h"
#include "hlog.h"

#define TAG "TAG_XBUF"


uint32_t xbuf_init(xbuf_handler *hdlr)
{
    iobuffer_init(&hdlr->read_io);
    return OK;
}

uint32_t xbuf_deinit(xbuf_handler *hdlr)
{
    iobuffer_deinit(&hdlr->read_io);
    return OK;
}

uint32_t xbuf_put(xbuf_handler *hdlr, const char *data, const uint32_t sz)
{
    if ( OK == iobuffer_appendData(&hdlr->read_io, data, sz) ) 
    {
       return xbuf_flush(hdlr);
    }
    return NG;
}



uint32_t xbuf_flush(xbuf_handler *hdlr)
{
     kpacket *packet = (kpacket*)hdlr->read_io.iodata;
     //hlogd("xbuf_flush len:%d magic:%x %d %d",packet->tlv.L, packet->tlv.magic,hdlr->read_io.size,sizeof(kpacket));
     while ( hdlr->read_io.size >= sizeof(kpacket) + packet->tlv.L ) /* 粘包 或 包不齐处理 */
        {
                if ( packet->tlv.magic == OS_PACKET_MAGIC && kpacket_calc_checksum(packet) == packet->tlv.checksum ){
                    {   /* 如果 注册了type 处理 */
                    	for ( uint16_t i=0; i< hdlr->ev_list_sz; i++ ){
                            //hlogd("xbuf_flush len:%d magic:%x",packet->tlv.T, hdlr->ev_list[i].event);
                    		if ( hdlr->ev_list[i].event == packet->tlv.T ){
                                hdlr->ev_list[i].on_event(packet);
                                break;
                    		}
                    	}
                    }
                
                    {   /* 增加未注册type的, packet 处理*/
                        if ( hdlr->on_packet )
                        {
                            hdlr->on_packet(packet);
                        }
                    }
                }else{
                    hloge("invalid %s magic:0x%x, calc_checksum:%x %x, V:%s", __func__, packet->tlv.magic, kpacket_calc_checksum(packet), packet->tlv.checksum,packet->tlv.V);
                }
                /* 删除packet占用的内存，后面的数据将前移到0位置 */ 
                iobuffer_erase(&hdlr->read_io, 0, sizeof(kpacket) + packet->tlv.L);  
        }
        
        return OK;
}



/************************************ for tester ************************************/
/* 应用层四步
**
** 一, 声明枚举指令 和 回调函数
** 二, 填写 packet_event 的 ev_list
** 三, 通过xbuf_init注册到xbuf
** 四, 收数xbuf_put到xbuf, 自动回调
**/

/* 第一步 */
enum{
    CMD_SYNC = 0x0001, /* 握手指令 */
};
    
static uint32_t on_sync(const kpacket *packet){
	hlogw("%s magic:0x%x, type:%x, extend:%u, len:%u, payload:%s", __func__, packet->tlv.magic, packet->tlv.T, packet->offset, packet->tlv.L, packet->tlv.V);
	return OK;
}


static packet_event s_ev_list[]={
	{CMD_SYNC, 	 on_sync},
};


/* 第二步 */

static xbuf_handler handler = {
    .ev_list     = s_ev_list, 
    .ev_list_sz  = sizeof(s_ev_list)/sizeof(s_ev_list[0]),
};

/* 第三和四步 */

static uint32_t kpacket_recv(char *data, uint32_t max_sz);
void xbuf_test()
{
    xbuf_init(&handler);
    
    {
        /* 用iobuffer */
        for ( uint32_t i=0; i<10; i++ )
        { 
            if ( iobuffer_freesize(&handler.read_io) < 1024 ) /* 如果预期接收的数据不小于1024大小（也可是256/512字节点）， 那么扩容一下， 随协议来定*/
            {
                iobuffer_reserve(&handler.read_io, 1024 + handler.read_io.size); /* 小于1024了申请多些内存 */
            }
            
            /*第一种： 直接读到xbuf的iobuffer, 减少一次内存拷贝 */
            uint32_t read_cnt  = kpacket_recv(handler.read_io.iodata + handler.read_io.size, iobuffer_freesize(&handler.read_io));
            if ( read_cnt > 0 )
            {
               handler.read_io.size += read_cnt;
               kpacket *packet = (kpacket*)handler.read_io.iodata;
               hlogd("xbuf_test read_cnt:%u %s",read_cnt, packet->tlv.V);
               xbuf_flush(&handler); /*将自动回调对应的on_type*/
            }
            //hlogd("xbuf_test i:%u",i);
        }
        hlogd("xbuf_test end");
    }
    
    
    xbuf_deinit(&handler);
}


/* 串口, rndis 等的接收*/
static uint32_t kpacket_recv(char *data, uint32_t max_sz)
{
    /*******这段为模拟发送端发送的数据        ，即接收*******/
    static uint32_t i;
    char str[128]; /* 没必要memset 或 ={0}, sprintf 会补 0 */
    sprintf(str, "{\"sync\":\"i m :%u\"}", i++);
    
    uint32_t size = strlen(str) + 1; /*+1 for '\0'*/
    

    kpacket *packet = kpacket(CMD_SYNC, size);
    kpacket_put_string(packet, str);
    kpacket_checksum(packet); /* 生成 crc16 */

    hlogd("%s magic:0x%x, calc_checksum:%x %x, V:%s", __func__, packet->tlv.magic, kpacket_calc_checksum(packet), packet->tlv.checksum, packet->tlv.V);
    #if 0
    send(packet, sizeof(kpacket)+packet->tlv.L); /* 发给接收端数据 */
    #endif 
    
    /*********************end***********************/
   
    /******* 这段为接收端数据拷贝到目标中data, 如iobuffer.iodata *******/
    #if 0
    recv_cnt = recv(data, max_sz); /* 发给接收端数据 */
    #else 
    int32_t recv_cnt = sizeof(kpacket) + packet->tlv.L;
    memcpy(data, packet, recv_cnt);
    #endif
   
    kpacket_dec(packet);/* 释放kpacket */
    
    return recv_cnt;
}
/************************************end************************************/


