#include "selfcare_res.h"
#include "utils_queue.h"
#include "selfcare_udp.h"
#include "selfcare_endecode.h"
#include "log.h"

extern selfcare_res_s *selfcare_assign_res();
extern void crm_delete_subscriber_profile(char *service_num, int account_type, int account_id);
extern int crm_prov_handle_response(selfcare_res_s *res);
extern ulong TransStrTimeToSecond(const char *str_time);//YYYY-MM-DD HH:MM:YY
extern int dba_crm_get_product_rent(int from, int package_id);
extern void _selfcare_udp_process();

/* 空闲资源队列*/
static queueADT g_res_queue;
static int g_res[SELFCARE_RES_NUM];

/* 资源 */
selfcare_res_s g_res_arr[SELFCARE_RES_NUM];

static int g_res_run_flag;

static int  _selfcare_fsm_sendudp(selfcare_res_s *res)
{
	int ret;

	/* 1. 解析selfcare系统发来的消息 */
	_rest_msg_s msg;
	memset(&msg, 0x00, sizeof(msg));
	ret = selfcare_decode(res->req,res->req_type, &msg);
	if(ret != SUCCESS)
	{
		LOG_E("[httpserv] decode failed\n");
		return ret;
	}
	LOG_D("[httpserv] decode suc. res_id[%d]\n", res->id);

	/* 2. 编码 */
	char buf[1024];
	int len;
	msg.header.src_ref = res->id;
	len = encode_rest(&msg, (u8*)buf);

	if(msg.msg_type == REST_CRM_DELETE_SUBS_REQ)
	{
		crm_delete_subscriber_profile(msg.msg.delete_subs.msisdn, msg.msg.delete_subs.account_type, msg.msg.delete_subs.account_id);
		if(msg.msg.delete_subs.account_type != 1)//not mobile
		{
		//return OK to CRM here
			res->resp.msg_type = REST_CRM_DELETE_SUBS_RES;
			res->resp.msg.delete_subs_res.result = 0;
			res->resp.msg.delete_subs_res.error_code = 2001;
			
			res->state = SELFCARE_WAIT_SEND2SELFCARE_RESP;
			return SUCCESS;
		}		
	}
	/* 3. 发送udp消息到 ocs */
	if(len > 0)
	{
		ret = selfcare_udp_send(buf, len);
		
		LOG_D("[httpserv] send udp suc.res_id[%d] ret[%d]\n", res->id, ret);
		return SUCCESS;
	}

	LOG_E("[httpserv] err.send udp err. res_id[%d]\n", res->id);
	return FAILURE;
}

static int  _selfcare_fsm_sendudp_local(selfcare_res_s *res, _rest_msg_s msg)
{
	int ret;
	char buf[1024];
	int len;

	msg.header.src_ref = res->id;
	len = encode_rest(&msg, (u8*)buf);

	/* 3. 发送udp消息到 ocs */
	if(len > 0)
	{
		ret = selfcare_udp_send(buf, len);
		
		LOG_D("[httpserv] send udp suc.res_id[%d] ret[%d]\n", res->id, ret);
		return SUCCESS;
	}

	LOG_E("[httpserv] err.send udp err. res_id[%d]\n", res->id);

	return FAILURE;
}

/* 发送回复到selfcare系统 */
static void _selfcare_fsm_send2selfcare(const selfcare_res_s *res)
{
	/* 编码 */
	char *buf = NULL;
	selfcare_encode(res->req_type, &res->resp, &buf);
	
	/* 回复 */
	selfcare_httpsrv_send(res->req, 200, buf);
}

void _selfcare_res_fsm(void)
//static void _selfcare_res_fsm(void)
{
    int i;
    selfcare_res_s *res;
	
    for(i = 1; i < SELFCARE_RES_NUM; ++i)
    {
        res = &g_res_arr[i];
	  res->timer++;
        switch(res->state)
        {
            case SELFCARE_IDLE:
                break;
            case SELFCARE_WAIT_SELFCARE_REQ:
                break;
            case SELFCARE_WAIT_SEND2OCS_REQ:
		   LOG_D("[httpserv] res_id[%d] state[%s->%s]\n",
					res->id, selfcare_res_stateprint(res->state), selfcare_res_stateprint(SELFCARE_WAIT_OCS_RESP));
		 
                _selfcare_fsm_sendudp(res);

                res->state = SELFCARE_WAIT_OCS_RESP;
		  res->timer = 0;

                break;
            case SELFCARE_WAIT_OCS_RESP:
			/* 3秒没有处理完就超时处理 */
			if(res->timer >= 3000)
			{
				// send httpserv time out ???
		   		LOG_D("[httpserv] res_id[%d] timeout state[%s->%s]\n",
					res->id, selfcare_res_stateprint(res->state), selfcare_res_stateprint(SELFCARE_RELEASE));

				res->state = SELFCARE_RELEASE; 
			}

                break;
            case SELFCARE_WAIT_SEND2SELFCARE_RESP:
			LOG_D("[httpserv] res_id[%d] state[%s->%s]\n",
						res->id, selfcare_res_stateprint(res->state), selfcare_res_stateprint(SELFCARE_RELEASE));
                
                	_selfcare_fsm_send2selfcare(res);

			res->state = SELFCARE_RELEASE; 
  		       res->timer = 0;

                break;
            case SELFCARE_LOCAL_INIT_REQ:
			LOG_D("[httpserv] res_id[%d] state[%s->%s]\n",
							res->id, selfcare_res_stateprint(res->state), selfcare_res_stateprint(SELFCARE_WAIT_OCS_RESP));
               	res->state = SELFCARE_WAIT_OCS_RESP;
		       res->timer = 0;

            //    _selfcare_fsm_sendudp(res);

                break;
            case SELFCARE_LOCAL_INIT_RESP:
				LOG_D("[httpserv] res_id[%d] state[%s->%s]\n",
							res->id, selfcare_res_stateprint(res->state), selfcare_res_stateprint(SELFCARE_RELEASE));
				
                	crm_prov_handle_response(res);
					
		   	res->state = SELFCARE_RELEASE; 
		       res->timer = 0;

            break;				
            case SELFCARE_RELEASE:
 		case SELFCARE_STATE_MAX:
		default:
				memset(&g_res_arr[i], 0x00, sizeof(selfcare_res_s));
				selfcare_res_release(i);
				LOG_D("[httpserv] release suc. res_id[%d] state[%s]\n",
								i, selfcare_res_stateprint(SELFCARE_IDLE));

             break;
        }
    }
}



/*--------------------------------------------------------*/
int crm_prov_mobile_prepaid_account(char sub_data[][1024], int cug_id, int user_class)
{//user class=1/2 local / tourist
	selfcare_res_s *res = selfcare_assign_res();
	_rest_msg_s *msg=NULL, rest_msg;

	if(res == NULL)
		return 0;


	msg = &rest_msg;
	msg->msg_type = REST_CRM_CREATE_ACCT_REQ;
	
	strcpy(msg->msg.create_acct.msisdn, sub_data[3]);	
	msg->msg.create_acct.customer_id = atoi(sub_data[6]);
	msg->msg.create_acct.account_id = atoi(sub_data[7]);
	msg->msg.create_acct.product_id = atoi(sub_data[8]);
	msg->msg.create_acct.plan_id = atoi(sub_data[14]);
	msg->msg.create_acct.user_class = user_class;
	msg->msg.create_acct.cug_id = cug_id;//atoi(sub_data[16]);
	msg->msg.create_acct.balance = atoi(sub_data[12]);

	msg->msg.create_acct.expiry_date = TransStrTimeToSecond(sub_data[13]);
	msg->msg.create_acct.birthday = TransStrTimeToSecond(sub_data[11]);
	msg->msg.create_acct.rent_charge = dba_crm_get_product_rent(0, msg->msg.create_acct.plan_id);

	res->local_init_db_key = atoi(sub_data[0]);
	res->local_init_flag = 1;
	res->local_init_oc = REST_CRM_CREATE_ACCT_REQ;
		
	_selfcare_fsm_sendudp_local(res, rest_msg);
   	res->state = SELFCARE_LOCAL_INIT_REQ;

	
	return 1;

}

int crm_prov_handle_response(selfcare_res_s *res)
{
	char sql[2048];
	
	if(res == NULL)
		return 0;
	
	switch(res->local_init_oc)
	{
		case REST_CRM_CREATE_ACCT_REQ:
			if(res->resp.msg.create_acct_res.error_code ==  OCS_RES_SUCCEED)
			{
				sprintf(sql, "UPDATE tb_sync_mobile set STATE=2, OPER_RESULT=1 where PRE_ID=%d", res->local_init_db_key);
			}
			else
			{
				sprintf(sql, "UPDATE tb_sync_mobile set STATE=2, OPER_RESULT=2 where PRE_ID=%d", res->local_init_db_key);
			}
			//subs_provisioning_update_result(sql);
		break;
		default:
		break;
	}
	return 1;
}

/*--------------------------------------------------------*/

static void *_selfcare_res_thread(void *data)
{
	prctl(PR_SET_NAME, "selfcare-fsm");

    while(g_res_run_flag)
    {
  	 _selfcare_udp_process();  
        _selfcare_res_fsm();
		usleep(1000);
    }
    pthread_exit(NULL);

	return NULL;
}


static int _selfcare_res_inittask()
{
    pthread_t handle;
	g_res_run_flag = 1;
    if(pthread_create(&handle, NULL, _selfcare_res_thread, NULL))
    {
        printf("Thread create err !!!\n");
		return FAILURE;
		
        if ( pthread_detach(handle) )
        {
            printf("Thread detached err !!!\n");
			return FAILURE;
        }
    }
	return SUCCESS;
}


int selfcare_res_get(int *res_id)
{
	queueElementT elem = QueueDelete(g_res_queue);
	if(elem == NULL)
	{
		LOG_E("[selfcare-res] get err. null\n");
		return FAILURE;
	}

    *res_id = *(int*)elem;

    return SUCCESS;
}

int selfcare_res_release(const int res_id)
{
    int ret;

    if(res_id>=SELFCARE_RES_NUM)
		return FAILURE;
	
    ret = QueueEnter(g_res_queue, &g_res[res_id]);
    if(ret != SUCCESS_QUEUE)
    {
        return FAILURE;
    }

    return SUCCESS;
}

const char *selfcare_res_stateprint(selfcare_state_e state)
{
    
    switch(state)
    {
        case SELFCARE_IDLE:
            return "idle";
        case SELFCARE_WAIT_SELFCARE_REQ:
            return "wait_selfcare_req";
		case SELFCARE_WAIT_SEND2OCS_REQ:
			return "send2ocs_req";
        case SELFCARE_WAIT_OCS_RESP:
            return "wait_ocs_resp";
		case SELFCARE_WAIT_SEND2SELFCARE_RESP:
			return "wait_send2selfcare_resp";
		case SELFCARE_LOCAL_INIT_REQ:
			return "local initiating process - send request";
		case SELFCARE_LOCAL_INIT_RESP:
			return "local initiating process-wait for response";			
		case SELFCARE_RELEASE:
			return "release";
        default:
            return "unknow";
    }
    return "unknow";
}

int selfcare_res_init(int argc, char **argv)
{
	int ret;

	/* 初始化空闲资源队列*/
	g_res_queue = QueueCreate(SELFCARE_RES_NUM);
	if(g_res_queue == NULL)
	{
		return FAILURE;
	}

	/* 加载空闲资源 */
	int i = 0;
	for(i = 1; i < SELFCARE_RES_NUM; ++i)
	{
		g_res[i] = i;
		ret = QueueEnter(g_res_queue, &g_res[i]);
		if(ret != SUCCESS_QUEUE)
		{
			return FAILURE;
		}
	}

    _selfcare_res_inittask();
    
	return SUCCESS;
}

void selfcare_res_uninit(void)
{
	QueueDestroy(g_res_queue);
    
    g_res_run_flag = 0;
}

