package Nrestful

import (
	"encoding/binary"
	"fmt"
	"net"
	"proxy/MsgDef"
	rdb "proxy/Nredis"
	"strconv"
	_ "strings"
	"time"

	l4g "proxy/logger" //"github.com/sirupsen/logrus"
)

var ocsConn *net.UDPConn

func closeConnect() {
	ocsConn.Close()
	ocsConn = nil
}

var locIp, ocsIp string
var locPort, ocsPort int

func Connect_ocs(loc string, rem string, loc_port int, rem_port int) error {
	locIp = loc
	ocsIp = rem
	locPort = loc_port
	ocsPort = rem_port
	
	return connect_ocs()
}

func connect_ocs() error {
	loc_ip := net.ParseIP(locIp)
	rem_ip := net.ParseIP(ocsIp)

	srcAddr := &net.UDPAddr{IP: loc_ip, Port: locPort}
	dstAddr := &net.UDPAddr{IP: rem_ip, Port: ocsPort}

	var err error
	ocsConn, err = net.DialUDP("udp", srcAddr, dstAddr)
	if err != nil {
		fmt.Println(err)
		return err
	}
	defer closeConnect()
	
	//conn.Write([]byte("hello"))
	data := make([]byte, 1500)
	//var recLen uint16 = 0
	//var msgId uint8 = 0
	for {
		n, err := ocsConn.Read(data)

		//msgId = data[1]
		//recLen = uint16(data[2])
		//recLen = (recLen << 8) + uint16(data[3])
		if err != nil {
			//break
		} else {
			// check param
			handle_udp_msg_from_ocs(data, n)
		}
		//fmt.Printf("read %s from <%s>\n", data[:n], conn.RemoteAddr())
	}
	l4g.RestLog.Errorln("ocs read thread exit")

	return nil
}

//type UdpMsgIE byte

const (
	IE_NULL = iota
    IE_SRC_REF // UdpMsgIE = 1
	IE_DST_REF
	IE_MSISDN
	IE_RESULT
	IE_ERROR_CODE
	IE_BALANCE// 6
	IE_MO_EXPIRY
	IE_MT_EXPIRY
	IE_USERNAME
	IE_PASSWORD
	IE_MSG_CONTENT //value=11
	IE_STATUS
	IE_REMARK
	IE_GROUP_NAME// 0x0e
	IE_MO_VOICE_MIN// in minute
	IE_REMAIN_MO_VOICE_SEC// in second
	IE_REMAIN_MO_VOICE_MIN// in minute
	IE_MT_VOICE_MIN// in minute
	IE_REMAIN_MT_VOICE_SEC// in second
	IE_REMAIN_MT_VOICE_MIN// in minute
	IE_SMS_NUM//value=21
	IE_REMAIN_SMS_NUM
	IE_DATA_VOL_MB// in MB
	IE_REMAIN_DATA_VOL_KB// in KB
	IE_REMAIN_DATA_VOL_MB// in MB
	IE_PAY_TYPE
	IE_AMOUNT
	IE_VALID_DAYS
	IE_EXPIRY_TIME
	IE_MSISDN_TRANS_OUT
	IE_MSISDN_TRANS_IN //value=31
	IE_BALANCE_AVAILABLE
	IE_RECHARGE_AMOUNT
	IE_RECHARGE_TYPE
	IE_RECHARGE_CARD_STATUS
	IE_RECHARGE_CARD_FACE_VALUE
	IE_RECHARGE_CARD_EXPIRED_TS
	IE_RECHARGE_CARD_UPDATED_TS
	IE_CUSTOMER_ID
	IE_ACCOUNT_ID
	IE_PRODUCT_ID//value=41
	IE_PLAN_ID
	IE_RENT_CHARGE
	IE_BIRTHDAY
	IE_SMS_CONTENT
	IE_SERVICE_TYPE
	IE_TARIIFF_PREFIX
	IE_TARIFF_UNIT
	IE_TARIFF_CHARGE
	IE_TARIFF_DISCOUNT
	IE_PLAN_VALUE//value=51
	IE_PLAN_USED_VALUE
	IE_BUNDLE_ID
	IE_CAUSE
	IE_SESS_FLAG
	IE_TIMESTAMP
	IE_CONSUME_VALUE
	IE_CALLED_NUMBER
	IE_UE_IP
	IE_GW_IP
	IE_CUG_ID
	IE_VAS_CUG_STATUS
	IE_SESS_UPDATE_TIME
	IE_PLAN_VALUE_ADD_THIS_TIME
	IE_USER_CLASS
	IE_MAX_NUM
)

func handle_udp_msg_from_ocs(buf []byte, msglen int) {
	var rsp RestRsp
	
	ret := Decode_udp_msg(buf, msglen, &rsp)
	if ret < 0 {
		l4g.RestLog.Errorf("Deocde UDP msg fail, msg[%v]", buf[:msglen])
		return
	}

	switch rsp.MsgType {
	case REST_CRM_UPDATE_PLAN_INFO_REQ:
		go handleUpdatePlanUsage(&rsp)
		return
	case REST_CRM_DELETE_SUBS_RES:
		handleOcsDeleteSubsRsp(&rsp)
	case REST_CRM_CREATE_ACCT_RES:
		//handleOcsDeleteSubsRsp(&rsp)
	case REST_CRM_UPDATE_SUBS_REQ:
		go handleOcsUpdateSubsReq(&rsp)
		return
	}

	l4g.RestLog.Debugf("Recv UDP msg from OCS, msg_id[%d], src[%d], dst[%d]", rsp.MsgType, rsp.Src_id, rsp.Dst_id)
	if rsp.Dst_id >= MAX_PORT_NUM {
		return
	}
	port := GetPortInfo(rsp.Dst_id, rsp.Src_id)
	if port == nil {
		l4g.RestLog.Errorf("Get port by dst_id[%d] fail, msg id[%d]", rsp.Dst_id, rsp.MsgType)
		return
	}
	l4g.RestLog.Debugf("Get port by dst_id[%d] from UDP rsp, msg id[%d]", rsp.Dst_id, rsp.MsgType)
	
	go func() {
		port.Rsp <- rsp
	}()
	
	return
}

func encode_udp_msg(req *RestReq, buf []byte) int {
	switch req.MsgType {
		case REST_SEND_AUTHCODE_REQ:
		case REST_QUERY_USERDATA_REQ:
		case REST_BUNDLE_SUBS_REQ:
		case REST_RECHARGE_REQ:
		case REST_TRANSFER_REQ:
		case REST_QUERY_BALANCE_REQ:
		case REST_CRM_CREATE_ACCT_REQ:
		case REST_CRM_UPDATE_SUBS_REQ:
		case REST_CRM_DELETE_SUBS_REQ:
		default:
			l4g.RestLog.Errorf("Encode rest unsupport msg id[%d]", req.MsgType)
			return 0
	}
	
	var msglen int = 0
	buf[msglen] = req.MsgType
	msglen++
	buf[msglen] = IE_SRC_REF
	msglen++
	buf[msglen] = 0x02
	msglen++
	binary.BigEndian.PutUint16(buf[msglen:msglen+2], req.Src_id)
	msglen += 2
	buf[msglen] = IE_DST_REF
	msglen++
	buf[msglen] = 0x02
	msglen++
	binary.BigEndian.PutUint16(buf[msglen:msglen+2], req.Dst_id)
	msglen += 2
	
	var vallen int = 0
	switch (req.MsgType) {
	case REST_SEND_AUTHCODE_REQ:
		l4g.RestLog.Debugf("Encode REST_SEND_AUTHCODE_REQ[%d], %#v", req.MsgType, req.AuthCodeReq)
		// IE_MSISDN
		buf[msglen] = IE_MSISDN
		msglen++
		vallen = len(req.AuthCodeReq.TelNumber)
		buf[msglen] = byte(vallen)
		msglen++
		copy(buf[msglen:msglen+vallen], ([]byte(req.AuthCodeReq.TelNumber)))
		msglen += vallen
	
		// IE_MSG_CONTENT
		buf[msglen] = IE_MSG_CONTENT
		msglen++
		vallen = len(req.AuthCodeReq.Content)
		binary.BigEndian.PutUint16(buf[msglen:msglen+2], uint16(vallen))
		msglen += 2
		copy(buf[msglen:msglen+vallen], ([]byte(req.AuthCodeReq.Content)))
		msglen += vallen

	case REST_QUERY_USERDATA_REQ:
		l4g.RestLog.Debugf("Encode REST_QUERY_USERDATA_REQ[%d], %#v", req.MsgType, req.QueryUserDataReq)
		// IE_MSISDN
		buf[msglen] = IE_MSISDN
		msglen++
		vallen = len(req.QueryUserDataReq.TelNumber)
		buf[msglen] = byte(vallen)
		msglen++
		copy(buf[msglen:msglen+vallen], ([]byte(req.QueryUserDataReq.TelNumber)))
		msglen += vallen
	
	case REST_BUNDLE_SUBS_REQ:
		l4g.RestLog.Debugf("Encode REST_BUNDLE_SUBS_REQ[%d], %#v", req.MsgType, req.BundleSubsReq)
		// IE_MSISDN
		buf[msglen] = IE_MSISDN
		msglen++
		vallen = len(req.BundleSubsReq.TelNumber)
		buf[msglen] = byte(vallen)
		msglen++
		copy(buf[msglen:msglen+vallen], ([]byte(req.BundleSubsReq.TelNumber)))
		msglen += vallen
	
		buf[msglen] = IE_PAY_TYPE
		msglen++
		buf[msglen] = 0x01
		msglen++
		pay_type, _ := strconv.Atoi(req.BundleSubsReq.PayType)
		buf[msglen]  =  uint8(pay_type)
		msglen += 0x01
		
		buf[msglen] = IE_AMOUNT
		msglen++
		buf[msglen] = 0x04
		msglen++
		amount, _ := strconv.Atoi(req.BundleSubsReq.ChargedAmount)
		binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(amount))
		msglen += 0x04
	
		buf[msglen] = IE_MO_VOICE_MIN
		msglen++
		buf[msglen] = 0x04
		msglen++
		moVocMin, _ := strconv.Atoi(req.BundleSubsReq.MoVoiceMinute)
		binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(moVocMin))
		msglen += 0x04
	
		buf[msglen] = IE_MT_VOICE_MIN
		msglen++
		buf[msglen] = 0x04
		msglen++
		mtVocMin, _ := strconv.Atoi(req.BundleSubsReq.MtVoiceMinute)
		binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(mtVocMin))
		msglen += 0x04
	
		buf[msglen] = IE_SMS_NUM
		msglen++
		buf[msglen] = 0x04
		msglen++
		smsNum, _ := strconv.Atoi(req.BundleSubsReq.SmsVolume)
		binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(smsNum))
		msglen += 0x04
	
		buf[msglen] = IE_DATA_VOL_MB
		msglen++
		buf[msglen] = 0x04
		msglen++
		dataVol, _ := strconv.Atoi(req.BundleSubsReq.DataVolume)
		binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(dataVol))
		msglen += 0x04

		buf[msglen] = IE_VALID_DAYS
		msglen++
		buf[msglen] = 0x04
		msglen++
		validDays, _ := strconv.Atoi(req.BundleSubsReq.ValidPeriod)
		binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(validDays))
		msglen += 0x04
	
	case REST_RECHARGE_REQ:
		l4g.RestLog.Debugf("Encode REST_RECHARGE_REQ[%d], %#v", req.MsgType, req.RechargeReq)
		// IE_MSISDN
		buf[msglen] = IE_MSISDN
		msglen++
		vallen = len(req.RechargeReq.TelNumber)
		buf[msglen] = byte(vallen)
		msglen++
		copy(buf[msglen:msglen+vallen], ([]byte(req.RechargeReq.TelNumber)))
		msglen += vallen

		buf[msglen] = IE_AMOUNT
		msglen++
		buf[msglen] = 0x04
		msglen++
		amount, _ := strconv.Atoi(req.RechargeReq.Amount)
		binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(amount))
		msglen += 0x04
	
		buf[msglen] = IE_RECHARGE_TYPE
		msglen++
		buf[msglen] = 0x01
		msglen++
		op_type, _ := strconv.Atoi(req.RechargeReq.OpType)
		buf[msglen]  =  uint8(op_type)
		msglen += 0x01
		
		buf[msglen] = IE_VALID_DAYS
		msglen++
		buf[msglen] = 0x02
		msglen++
		valid_days, _ := strconv.Atoi(req.RechargeReq.ValidyDays)
		binary.BigEndian.PutUint16(buf[msglen:msglen+2], uint16(valid_days))
		msglen += 0x02
	
	case REST_TRANSFER_REQ:
		l4g.RestLog.Debugf("Encode REST_TRANSFER_REQ[%d], %#v", req.MsgType, req.TransferReq)
		// IE_MSISDN_TRANS_OUT
		buf[msglen] = IE_MSISDN_TRANS_OUT
		msglen++
		vallen = len(req.TransferReq.TransferOut)
		buf[msglen] = byte(vallen)
		msglen++
		copy(buf[msglen:msglen+vallen], ([]byte(req.TransferReq.TransferOut)))
		msglen += vallen

		buf[msglen] = IE_MSISDN_TRANS_IN
		msglen++
		vallen = len(req.TransferReq.TransferIn)
		buf[msglen] = byte(vallen)
		msglen++
		copy(buf[msglen:msglen+vallen], ([]byte(req.TransferReq.TransferIn)))
		msglen += vallen

		buf[msglen] = IE_AMOUNT
		msglen++
		buf[msglen] = 0x04
		msglen++
		amount, _ := strconv.Atoi(req.TransferReq.Amount)
		binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(amount))
		msglen += 0x04
	
	case REST_QUERY_BALANCE_REQ:
		l4g.RestLog.Debugf("Encode REST_QUERY_BALANCE_REQ[%d], %#v", req.MsgType, req.QueryBalanceReq)
		// IE_MSISDN
		buf[msglen] = IE_MSISDN
		msglen++
		vallen = len(req.QueryBalanceReq.TelNumber)
		buf[msglen] = byte(vallen)
		msglen++
		copy(buf[msglen:msglen+vallen], ([]byte(req.QueryBalanceReq.TelNumber)))
		msglen += vallen
	
	case REST_CRM_CREATE_ACCT_REQ:
		l4g.RestLog.Debugf("Encode REST_CRM_CREATE_ACCT_REQ[%d], %#v", req.MsgType, req.CreateAccountReq)
		// IE_MSISDN
		buf[msglen] = IE_MSISDN
		msglen++
		vallen = len(req.CreateAccountReq.ServiceNbr)
		buf[msglen] = byte(vallen)
		msglen++
		copy(buf[msglen:msglen+vallen], ([]byte(req.CreateAccountReq.ServiceNbr)))
		msglen += vallen
	
		buf[msglen] = IE_CUSTOMER_ID
		msglen++
		buf[msglen] = 0x04
		msglen++
		custId, _ := strconv.Atoi(req.CreateAccountReq.CustId)
		binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(custId))
		msglen += 0x04
	
		buf[msglen] = IE_ACCOUNT_ID
		msglen++
		buf[msglen] = 0x04
		msglen++
		acctId, _ := strconv.Atoi(req.CreateAccountReq.AccountId)
		binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(acctId))
		msglen += 0x04
	
		buf[msglen] = IE_PRODUCT_ID
		msglen++
		buf[msglen] = 0x04
		msglen++
		prdId, _ := strconv.Atoi(req.CreateAccountReq.ProductInstId)
		binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(prdId))
		msglen += 0x04
	
		buf[msglen] = IE_PLAN_ID
		msglen++
		buf[msglen] = 0x04
		msglen++
		planId, _ := strconv.Atoi(req.CreateAccountReq.PackageId)
		binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(planId))
		msglen += 0x04
	
		buf[msglen] = IE_BALANCE
		msglen++
		buf[msglen] = 0x04
		msglen++
		balance, _ := strconv.Atoi(req.CreateAccountReq.Balance)
		binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(balance))
		msglen += 0x04
	
		buf[msglen] = IE_EXPIRY_TIME
		msglen++
		buf[msglen] = 0x04
		msglen++
		expire_time, err := time.Parse("2006-01-02 15:04:05", req.CreateAccountReq.BalanceExpDate)
		if err != nil {
			l4g.RestLog.Errorf("Error CreateAccountReq BalanceExpDate[%s]", req.CreateAccountReq.BalanceExpDate)
			return -1
		}
		binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(expire_time.Unix()))
		msglen += 0x04
	
		buf[msglen] = IE_RENT_CHARGE
		msglen++
		buf[msglen] = 0x04
		msglen++
		rent_charge, _ := strconv.Atoi(req.CreateAccountReq.RentCharge)
		binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(rent_charge))
		msglen += 0x04
	
		buf[msglen] = IE_BIRTHDAY
		msglen++
		buf[msglen] = 0x04
		msglen++
		birthday, err := time.Parse("2006-01-02", req.CreateAccountReq.Birthday)
		if err != nil {
			l4g.RestLog.Errorf("Error CreateAccountReq Birthday[%s]", req.CreateAccountReq.Birthday)
			return -1
		}
		binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(birthday.Unix()))
		msglen += 0x04
	
		buf[msglen] = IE_CUG_ID
		msglen++
		buf[msglen] = 0x04
		msglen++
		cugId, _ := strconv.Atoi(req.CreateAccountReq.CugId)
		binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(cugId))
		msglen += 0x04

		buf[msglen] = IE_USER_CLASS
		msglen++
		buf[msglen] = 0x01
		msglen++
		userClass, _ := strconv.Atoi(req.CreateAccountReq.UserClass)
		buf[msglen] = byte(userClass)
		msglen += 0x01

	case REST_CRM_UPDATE_SUBS_REQ:
		l4g.RestLog.Debugf("Encode REST_CRM_UPDATE_SUBS_REQ[%d], %#v", req.MsgType, req.UpdateSubsReq)
		// IE_MSISDN
		buf[msglen] = IE_MSISDN
		msglen++
		vallen = len(req.UpdateSubsReq.TelNumber)
		buf[msglen] = byte(vallen)
		msglen++
		copy(buf[msglen:msglen+vallen], ([]byte(req.UpdateSubsReq.TelNumber)))
		msglen += vallen

		buf[msglen] = IE_ACCOUNT_ID
		msglen++
		buf[msglen] = 0x04
		msglen++
		acctId, _ := strconv.Atoi(req.UpdateSubsReq.AccountId)
		binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(acctId))
		msglen += 0x04
	
		if (len(req.UpdateSubsReq.Status) > 0) {
			buf[msglen] = IE_STATUS
			msglen++
			buf[msglen] = 0x01
			msglen++
			status, _ := strconv.Atoi(req.UpdateSubsReq.Status)
			buf[msglen] = byte(status)
			msglen += 0x01
		}
		
		if (len(req.UpdateSubsReq.Balance) > 0) {
			buf[msglen] = IE_BALANCE
			msglen++
			buf[msglen] = 0x04
			msglen++
			balance, _ := strconv.Atoi(req.UpdateSubsReq.Balance)
			binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(balance))
			msglen += 0x04
		}

		if (len(req.UpdateSubsReq.BalanceExpDate) > 0) {
			buf[msglen] = IE_EXPIRY_TIME
			msglen++
			buf[msglen] = 0x04
			msglen++
			expiryTime, err := time.Parse("2006-01-02 15:04:05", req.UpdateSubsReq.BalanceExpDate)
			if err != nil {
				l4g.RestLog.Errorf("Error UpdateSubsReq BalanceExpDate[%s]", req.UpdateSubsReq.BalanceExpDate)
				return -1
			}
			binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(expiryTime.Unix()))
			msglen += 0x04
		}
	
		if (len(req.UpdateSubsReq.PackageId) > 0) {
			buf[msglen] = IE_PLAN_ID
			msglen++
			buf[msglen] = 0x04
			msglen++
			planId, _ := strconv.Atoi(req.UpdateSubsReq.PackageId)
			binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(planId))
			msglen += 0x04
		}
	
		if (len(req.UpdateSubsReq.RentCharge) > 0) {
			buf[msglen] = IE_RENT_CHARGE
			msglen++
			buf[msglen] = 0x04
			msglen++
			rentCharge, _ := strconv.Atoi(req.UpdateSubsReq.RentCharge)
			binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(rentCharge))
			msglen += 0x04
		}
	
		if (len(req.UpdateSubsReq.VasCugStatus) > 0) {
			buf[msglen] = IE_VAS_CUG_STATUS
			msglen++
			buf[msglen] = 0x01
			msglen++
			vasCugStatus, _ := strconv.Atoi(req.UpdateSubsReq.VasCugStatus)
			buf[msglen] = byte(vasCugStatus)
			msglen += 0x01
		}

	case REST_CRM_DELETE_SUBS_REQ:
		l4g.RestLog.Debugf("Encode REST_CRM_DELETE_SUBS_REQ[%d], %#v", req.MsgType, req.DeleteSubsReq)
		// IE_MSISDN
		buf[msglen] = IE_MSISDN
		msglen++
		vallen = len(req.DeleteSubsReq.TelNumber)
		buf[msglen] = byte(vallen)
		msglen++
		copy(buf[msglen:msglen+vallen], ([]byte(req.DeleteSubsReq.TelNumber)))
		msglen += vallen

		buf[msglen] = IE_CAUSE
		msglen++
		buf[msglen] = 0x01
		msglen++
		buf[msglen] = 0
		msglen += 0x01

	default:
		return 0
	}
	
	return msglen
}

func SendOcsUdpReq(req *RestReq) {
	if ocsConn == nil {
		return
	}
	
	l4g.RestLog.Debugf("Send UDP msg to OCS, msg_id[%d], src[%d], dst[%d]", req.MsgType, req.Src_id, req.Dst_id)

	buf := make([]byte, 1024)

	msglen := encode_udp_msg(req, buf)

	if msglen > 0 {
		ocsConn.Write([]byte(buf[:msglen]))
	}

	return
}

func SendNtfSms2Ocs(serviceNbr string, smsContent string) {
	var req RestReq
	req.MsgType = REST_SEND_AUTHCODE_REQ
	req.Src_id = 0xFFFF
	req.Dst_id = 0xFFFF
	req.AuthCodeReq.TelNumber = serviceNbr
	req.AuthCodeReq.Content = smsContent

	SendOcsUdpReq(&req)
}

func SendCrtAcct2Ocs(serviceNbr string, ai *MsgDef.ChgSyncMobile, cugId, userClass, rent int) {
	var req RestReq
	req.MsgType = REST_CRM_CREATE_ACCT_REQ
	req.Src_id = 0xFFFF
	req.Dst_id = 0xFFFF
	req.CreateAccountReq.ServiceNbr = serviceNbr
	req.CreateAccountReq.CustId = strconv.Itoa(ai.CustId)
	req.CreateAccountReq.AccountId = strconv.Itoa(ai.AcctId)
	req.CreateAccountReq.ProductInstId = strconv.Itoa(ai.PrdInstId)
	req.CreateAccountReq.PackageId = strconv.Itoa(ai.OfrId)
	req.CreateAccountReq.UserClass = strconv.Itoa(userClass)
	req.CreateAccountReq.CugId = strconv.Itoa(cugId)
	req.CreateAccountReq.Balance = strconv.Itoa(ai.Balance)

	//t, _ := time.Parse("2006-01-02 15:04:05", ai.BirthDate)
	req.CreateAccountReq.Birthday = ai.BirthDate
	//t, _ := time.Parse("2006-01-02 15:04:05", ai.BalanceExpDate)
	req.CreateAccountReq.BalanceExpDate = ai.BalanceExpDate
	req.CreateAccountReq.RentCharge = strconv.Itoa(rent)

	SendOcsUdpReq(&req)
}

func CreateAcct2Ocs(serviceNbr string, ai *MsgDef.ChgSyncMobile, cugId, userClass, rent int, key string) {
	var req RestReq
	req.MsgType = REST_CRM_CREATE_ACCT_REQ
	req.Src_id = 0xFFFF
	req.Dst_id = 0xFFFF
	req.CreateAccountReq.ServiceNbr = serviceNbr
	req.CreateAccountReq.CustId = strconv.Itoa(ai.CustId)
	req.CreateAccountReq.AccountId = strconv.Itoa(ai.AcctId)
	req.CreateAccountReq.ProductInstId = strconv.Itoa(ai.PrdInstId)
	req.CreateAccountReq.PackageId = strconv.Itoa(ai.OfrId)
	req.CreateAccountReq.UserClass = strconv.Itoa(userClass)
	req.CreateAccountReq.CugId = strconv.Itoa(cugId)
	req.CreateAccountReq.Balance = strconv.Itoa(ai.Balance)

	//t, _ := time.Parse("2006-01-02 15:04:05", ai.BirthDate)
	req.CreateAccountReq.Birthday = ai.BirthDate
	//t, _ := time.Parse("2006-01-02 15:04:05", ai.BalanceExpDate)
	req.CreateAccountReq.BalanceExpDate = ai.BalanceExpDate
	req.CreateAccountReq.RentCharge = strconv.Itoa(rent)

	l4g.RestLog.Debugf("Got createAcct request: %v", req.CreateAccountReq)

	// handle ==========================================
	port := AssignPort(&req)
	if port == nil {
		l4g.RestLog.Warnf("Assign port for createAcct request fail, serviceNbr[%s], key[%s]", serviceNbr, key)
		return
	}
	l4g.RestLog.Debugf("Assign port for createAcct request, serviceNbr, src[%d], dst[%d]", serviceNbr, req.Src_id, req.Dst_id)

	ocsRsp := getOcsRsp(&req, port)
	if ocsRsp == nil {
		l4g.RestLog.Warnf("getOcsRsp timeout for createAcct request, serviceNbr[%s], key[%s]", serviceNbr, key)
	} else {
		l4g.RestLog.Infof("getOcsRsp succ for createAcct request, serviceNbr[%s], key[%s]", serviceNbr, key)
		rdb.RdsDelMsg2OcsKey(key)
	}

	return
}
