package Nrestful

import (
	"time"
	"encoding/binary"
	_ "strings"
	"strconv"
	
	l4g "proxy/logger"//"github.com/sirupsen/logrus"
)

func decode_authcode_rsp(buf []byte, msglen int, rsp *RestRsp) int {
	var offset int = 0
	var tag byte = 0
	var vallen byte = 0
	var result byte = 1

	for {
		if offset >= msglen {
			break
		}
		tag = buf[offset];
		offset++
		vallen = buf[offset];
		offset++

		switch tag {
		case IE_SRC_REF:
			rsp.Src_id = binary.BigEndian.Uint16(buf[offset:offset+2])
		case IE_DST_REF:
			rsp.Dst_id = binary.BigEndian.Uint16(buf[offset:offset+2])
		case IE_RESULT:
			result = buf[offset]
			if result == 0 {
				rsp.AuthCodeRsp.Code = strconv.Itoa(int(ERRCODE_SUCCESS))
				rsp.AuthCodeRsp.Message = Rest_proxy_errcodemsg(ERRCODE_SUCCESS)
			}
		case IE_ERROR_CODE:
			err_code := binary.BigEndian.Uint32(buf[offset:offset+4])
			rsp.AuthCodeRsp.Code = strconv.Itoa(int(err_code))
			rsp.AuthCodeRsp.Message = Rest_proxy_errcodemsg(err_code)
		default:
		}
		offset += int(vallen)
	}
	
	l4g.RestLog.Debugf("decode_authcode_rsp: %#v", rsp.AuthCodeRsp)
	
	return 0;
}

func decode_query_userData_rsp(buf []byte, msglen int, rsp *RestRsp) int {
	var offset int = 0
	var tag byte = 0
	var vallen byte = 0
	var result byte = 1

	for {
		if offset >= msglen {
			break
		}
		tag = buf[offset];
		offset++
		vallen = buf[offset];
		offset++

		switch tag {
		case IE_SRC_REF:
			rsp.Src_id = binary.BigEndian.Uint16(buf[offset:offset+2])
		case IE_DST_REF:
			rsp.Dst_id = binary.BigEndian.Uint16(buf[offset:offset+2])
		case IE_RESULT:
			result = buf[offset]
			if result == 0 {
				rsp.QueryUserDataRsp.Code = strconv.Itoa(int(ERRCODE_SUCCESS))
				rsp.QueryUserDataRsp.Message = Rest_proxy_errcodemsg(ERRCODE_SUCCESS)
			}
		case IE_ERROR_CODE:
			err_code := binary.BigEndian.Uint32(buf[offset:offset+4])
			rsp.QueryUserDataRsp.Code = strconv.Itoa(int(err_code))
			rsp.QueryUserDataRsp.Message = Rest_proxy_errcodemsg(err_code)
		case IE_MSISDN:
			rsp.QueryUserDataRsp.TelNumber = string(buf[offset:offset+int(vallen)])
		case IE_REMARK:
			rsp.QueryUserDataRsp.Remark = string(buf[offset:offset+int(vallen)])
		case IE_GROUP_NAME:
			rsp.QueryUserDataRsp.UserGroupName = string(buf[offset:offset+int(vallen)])
		case IE_STATUS:
			rsp.QueryUserDataRsp.Status = strconv.Itoa(int(buf[offset]))
		case IE_BALANCE:
			rsp.QueryUserDataRsp.Balance = strconv.Itoa(int(binary.BigEndian.Uint32(buf[offset:offset+4])))
		case IE_EXPIRY_TIME:
			tm := time.Unix(int64(binary.BigEndian.Uint64(buf[offset:offset+8])), 0)
			rsp.QueryUserDataRsp.ExpireDate = tm.Format("2006-01-02 15:04:05")
		case IE_REMAIN_MO_VOICE_MIN:
			rsp.QueryUserDataRsp.RemainMoVoiceMinute = strconv.Itoa(int(binary.BigEndian.Uint32(buf[offset:offset+4])))
	    case IE_REMAIN_MT_VOICE_MIN:
			rsp.QueryUserDataRsp.RemainMtVoiceMinute = strconv.Itoa(int(binary.BigEndian.Uint32(buf[offset:offset+4])))
		case IE_REMAIN_SMS_NUM:
			rsp.QueryUserDataRsp.RemainSmsVolume = strconv.Itoa(int(binary.BigEndian.Uint32(buf[offset:offset+4])))
		case IE_REMAIN_DATA_VOL_MB:
			rsp.QueryUserDataRsp.RemainDataVolume = strconv.Itoa(int(binary.BigEndian.Uint32(buf[offset:offset+4])))
		default:
		}
		offset += int(vallen)
	}
	
	l4g.RestLog.Debugf("decode_query_userData_rsp: %#v", rsp.QueryUserDataRsp)
	
	return 0;
}

func decode_bundleSubs_rsp(buf []byte, msglen int, rsp *RestRsp) int {
	var offset int = 0
	var tag byte = 0
	var vallen byte = 0
	var result byte = 1

	for {
		if offset >= msglen {
			break
		}
		tag = buf[offset];
		offset++
		vallen = buf[offset];
		offset++

		switch tag {
		case IE_SRC_REF:
			rsp.Src_id = binary.BigEndian.Uint16(buf[offset:offset+2])
		case IE_DST_REF:
			rsp.Dst_id = binary.BigEndian.Uint16(buf[offset:offset+2])
		case IE_RESULT:
			result = buf[offset]
			if result == 0 {
				rsp.BundleSubsRsp.Code = strconv.Itoa(int(ERRCODE_SUCCESS))
				rsp.BundleSubsRsp.Message = Rest_proxy_errcodemsg(ERRCODE_SUCCESS)
			}
		case IE_ERROR_CODE:
			err_code := binary.BigEndian.Uint32(buf[offset:offset+4])
			rsp.BundleSubsRsp.Code = strconv.Itoa(int(err_code))
			rsp.BundleSubsRsp.Message = Rest_proxy_errcodemsg(err_code)
		default:
		}
		offset += int(vallen)
	}
	
	l4g.RestLog.Debugf("decode_bundleSubs_rsp: %#v", rsp.BundleSubsRsp)
	return 0
}

func decode_query_balance_rsp(buf []byte, msglen int, rsp *RestRsp) int {
	var offset int = 0
	var tag byte = 0
	var vallen byte = 0
	var result byte = 1

	for {
		if offset >= msglen {
			break
		}
		tag = buf[offset];
		offset++
		vallen = buf[offset];
		offset++

		switch tag {
		case IE_SRC_REF:
			rsp.Src_id = binary.BigEndian.Uint16(buf[offset:offset+2])
		case IE_DST_REF:
			rsp.Dst_id = binary.BigEndian.Uint16(buf[offset:offset+2])
		case IE_RESULT:
			result = buf[offset]
			if result == 0 {
				rsp.QueryBalanceRsp.Code = strconv.Itoa(int(ERRCODE_SUCCESS))
				rsp.QueryBalanceRsp.Message = Rest_proxy_errcodemsg(ERRCODE_SUCCESS)
			}
		case IE_ERROR_CODE:
			err_code := binary.BigEndian.Uint32(buf[offset:offset+4])
			rsp.QueryBalanceRsp.Code = strconv.Itoa(int(err_code))
			rsp.QueryBalanceRsp.Message = Rest_proxy_errcodemsg(err_code)
		case IE_STATUS:
			rsp.QueryBalanceRsp.Status = strconv.Itoa(int(buf[offset]))
		case IE_BALANCE:
			rsp.QueryBalanceRsp.Balance = strconv.Itoa(int(binary.BigEndian.Uint32(buf[offset:offset+4])))
		case IE_MO_EXPIRY:
			tm := time.Unix(int64(binary.BigEndian.Uint32(buf[offset:offset+4])), 0)
			rsp.QueryBalanceRsp.ExpireDate = tm.Format("2006-01-02 15:04:05")
		default:
		}
		offset += int(vallen)
	}
	
	l4g.RestLog.Debugf("decode_query_balance_rsp: %#v", rsp.QueryBalanceRsp)
	
	return 0
}

func decode_recharge_rsp(buf []byte, msglen int, rsp *RestRsp) int {
	var offset int = 0
	var tag byte = 0
	var vallen byte = 0
	var result byte = 1

	for {
		if offset >= msglen {
			break
		}
		tag = buf[offset];
		offset++
		vallen = buf[offset];
		offset++

		switch tag {
		case IE_SRC_REF:
			rsp.Src_id = binary.BigEndian.Uint16(buf[offset:offset+2])
		case IE_DST_REF:
			rsp.Dst_id = binary.BigEndian.Uint16(buf[offset:offset+2])
		case IE_RESULT:
			result = buf[offset]
			if result == 0 {
				rsp.RechargeRsp.Code = strconv.Itoa(int(ERRCODE_SUCCESS))
				rsp.RechargeRsp.Message = Rest_proxy_errcodemsg(ERRCODE_SUCCESS)
			}
		case IE_ERROR_CODE:
			var err_code uint32
			if vallen == 1 {
				err_code = uint32(buf[offset])
			} else {
				err_code = binary.BigEndian.Uint32(buf[offset:offset+4])
			}
			
			rsp.RechargeRsp.Code = strconv.Itoa(int(err_code))
			rsp.RechargeRsp.Message = Rest_proxy_errcodemsg(err_code)
		case IE_STATUS:
			rsp.RechargeRsp.Status = strconv.Itoa(int(buf[offset]))
		case IE_BALANCE:
			rsp.RechargeRsp.Balance = strconv.Itoa(int(binary.BigEndian.Uint32(buf[offset:offset+4])))
		case IE_MO_EXPIRY:
			tm := time.Unix(int64(binary.BigEndian.Uint32(buf[offset:offset+4])), 0)
			rsp.RechargeRsp.ExpiredTimestamp = tm.Format("2006-01-02 15:04:05")
		default:
		}
		offset += int(vallen)
	}
	
	l4g.RestLog.Debugf("decode_recharge_rsp: %#v", rsp.RechargeRsp)
	
	return 0
}

func decode_transfer_rsp(buf []byte, msglen int, rsp *RestRsp) int {
	var offset int = 0
	var tag byte = 0
	var vallen byte = 0
	var result byte = 1

	for {
		if offset >= msglen {
			break
		}
		tag = buf[offset];
		offset++
		vallen = buf[offset];
		offset++

		switch tag {
		case IE_SRC_REF:
			rsp.Src_id = binary.BigEndian.Uint16(buf[offset:offset+2])
		case IE_DST_REF:
			rsp.Dst_id = binary.BigEndian.Uint16(buf[offset:offset+2])
		case IE_RESULT:
			result = buf[offset]
			if result == 0 {
				rsp.TransferRsp.Code = strconv.Itoa(int(ERRCODE_SUCCESS))
				rsp.TransferRsp.Message = Rest_proxy_errcodemsg(ERRCODE_SUCCESS)
			}
		case IE_ERROR_CODE:
			var err_code uint32
			if vallen == 1 {
				err_code = uint32(buf[offset])
			} else {
				err_code = binary.BigEndian.Uint32(buf[offset:offset+4])
			}
			
			rsp.TransferRsp.Code = strconv.Itoa(int(err_code))
			rsp.TransferRsp.Message = Rest_proxy_errcodemsg(err_code)
        case IE_AMOUNT:
        	rsp.TransferRsp.Balance = strconv.Itoa(int(binary.BigEndian.Uint32(buf[offset:offset+4])))
		default:
		}
		offset += int(vallen)
	}
	
	l4g.RestLog.Debugf("decode_transfer_rsp: %#v", rsp.TransferRsp)
	
	return 0
}

func decode_create_acct_rsp(buf []byte, msglen int, rsp *RestRsp) int {
	var offset int = 0
	var tag byte = 0
	var vallen byte = 0
	var result byte = 1

	for {
		if offset >= msglen {
			break
		}
		tag = buf[offset];
		offset++
		vallen = buf[offset];
		offset++

		switch tag {
		case IE_SRC_REF:
			rsp.Src_id = binary.BigEndian.Uint16(buf[offset:offset+2])
		case IE_DST_REF:
			rsp.Dst_id = binary.BigEndian.Uint16(buf[offset:offset+2])
		case IE_RESULT:
			result = buf[offset]
			if result == 0 {
				rsp.CreateAccountRsp.Code = strconv.Itoa(int(ERRCODE_SUCCESS))
				rsp.CreateAccountRsp.Message = Rest_proxy_errcodemsg(ERRCODE_SUCCESS)
			}
		case IE_ERROR_CODE:
			var err_code uint32
			if vallen == 1 {
				err_code = uint32(buf[offset])
			} else {
				err_code = binary.BigEndian.Uint32(buf[offset:offset+4])
			}
			
			rsp.CreateAccountRsp.Code = strconv.Itoa(int(err_code))
			rsp.CreateAccountRsp.Message = Rest_proxy_errcodemsg(err_code)
		default:
		}
		offset += int(vallen)
	}
	
	l4g.RestLog.Debugf("decode_create_acct_rsp: %#v", rsp.CreateAccountRsp)
	
	return 0
}

func decode_update_subs_req(buf []byte, msglen int, rsp *RestRsp) int {
	var offset int = 0
	var tag byte = 0
	var vallen byte = 0

	rsp.UpdateSubsReq.OptFlag = 0
	for {
		if offset >= msglen {
			break
		}
		tag = buf[offset]
		offset++
		vallen = buf[offset]
		offset++

		switch tag {
		case IE_SRC_REF:
			rsp.Src_id = binary.BigEndian.Uint16(buf[offset:offset+2])
		case IE_DST_REF:
			rsp.Dst_id = binary.BigEndian.Uint16(buf[offset:offset+2])
		case IE_MSISDN:
			rsp.UpdateSubsReq.TelNumber = string(buf[offset:offset+int(vallen)])
		case IE_ACCOUNT_ID:
			rsp.UpdateSubsReq.AccountIdU32 = binary.BigEndian.Uint32(buf[offset:offset+4])
		case IE_STATUS:
			rsp.UpdateSubsReq.StatusU8 = buf[offset]
			rsp.UpdateSubsReq.OptFlag |= 0x01
		case IE_BALANCE:
			rsp.UpdateSubsReq.BalanceU32 = binary.BigEndian.Uint32(buf[offset:offset+4])
			rsp.UpdateSubsReq.OptFlag |= 0x02
		case IE_EXPIRY_TIME:
			rsp.UpdateSubsReq.ExpDateU32 = binary.BigEndian.Uint32(buf[offset:offset+4])
			rsp.UpdateSubsReq.OptFlag |= 0x04
		case IE_PLAN_ID:
			rsp.UpdateSubsReq.PackageIdU32 = binary.BigEndian.Uint32(buf[offset:offset+4])
			rsp.UpdateSubsReq.OptFlag |= 0x08
		case IE_RENT_CHARGE:
			rsp.UpdateSubsReq.RentChargeU32 = binary.BigEndian.Uint32(buf[offset:offset+4])
			rsp.UpdateSubsReq.OptFlag |= 0x10
		case IE_VAS_CUG_STATUS:
			rsp.UpdateSubsReq.VasCugStatusU8 = buf[offset]
			rsp.UpdateSubsReq.OptFlag |= 0x20
		default:
		}
		offset += int(vallen)
	}

	l4g.RestLog.Debugf("decode_update_subs_req: %#v", rsp.UpdateSubsReq)

	return 0
}

func decode_update_subs_rsp(buf []byte, msglen int, rsp *RestRsp) int {
	var offset int = 0
	var tag byte = 0
	var vallen byte = 0
	var result byte = 1

	for {
		if offset >= msglen {
			break
		}
		tag = buf[offset];
		offset++
		vallen = buf[offset];
		offset++

		switch tag {
		case IE_SRC_REF:
			rsp.Src_id = binary.BigEndian.Uint16(buf[offset:offset+2])
		case IE_DST_REF:
			rsp.Dst_id = binary.BigEndian.Uint16(buf[offset:offset+2])
		case IE_RESULT:
			result = buf[offset]
			if result == 0 {
				rsp.UpdateSubsRsp.Code = strconv.Itoa(int(ERRCODE_SUCCESS))
				rsp.UpdateSubsRsp.Message = Rest_proxy_errcodemsg(ERRCODE_SUCCESS)
			}
		case IE_ERROR_CODE:
			var err_code uint32
			if vallen == 1 {
				err_code = uint32(buf[offset])
			} else {
				err_code = binary.BigEndian.Uint32(buf[offset:offset+4])
			}
			
			rsp.UpdateSubsRsp.Code = strconv.Itoa(int(err_code))
			rsp.UpdateSubsRsp.Message = Rest_proxy_errcodemsg(err_code)
		default:
		}
		offset += int(vallen)
	}
	
	l4g.RestLog.Debugf("decode_update_subs_rsp: %#v", rsp.UpdateSubsRsp)
	
	return 0
}

func decode_delete_subs_rsp(buf []byte, msglen int, rsp *RestRsp) int {
	var offset int = 0
	var tag byte = 0
	var vallen byte = 0
	var result byte = 1

	for {
		if offset >= msglen {
			break
		}
		tag = buf[offset]
		offset++
		vallen = buf[offset]
		offset++

		switch tag {
		case IE_SRC_REF:
			rsp.Src_id = binary.BigEndian.Uint16(buf[offset:offset+2])
		case IE_DST_REF:
			rsp.Dst_id = binary.BigEndian.Uint16(buf[offset:offset+2])
		case IE_RESULT:
			result = buf[offset]
			rsp.DeleteSubsRsp.Result = result
			if result == 0 {
				rsp.DeleteSubsRsp.Code = strconv.Itoa(int(ERRCODE_SUCCESS))
				rsp.DeleteSubsRsp.Message = Rest_proxy_errcodemsg(ERRCODE_SUCCESS)
			}
		case IE_ERROR_CODE:
			var err_code uint32
			if vallen == 1 {
				err_code = uint32(buf[offset])
			} else {
				err_code = binary.BigEndian.Uint32(buf[offset:offset+4])
			}

			rsp.DeleteSubsRsp.ErrorCode = err_code
			rsp.DeleteSubsRsp.Code = strconv.Itoa(int(err_code))
			rsp.DeleteSubsRsp.Message = Rest_proxy_errcodemsg(err_code)
		default:
		}
		offset += int(vallen)
	}

	l4g.RestLog.Debugf("decode_update_subs_rsp: %#v", rsp.UpdateSubsRsp)

	return 0
}

func decodeUpdateBundleUsageReq(buf []byte, msglen int, rsp *RestRsp) int {
	var offset int = 0
	var tag byte = 0
	var vallen byte = 0

	for {
		if offset >= msglen {
			break
		}
		tag = buf[offset]
		offset++
		vallen = buf[offset]
		offset++

		switch tag {
		case IE_SRC_REF:
			rsp.Src_id = binary.BigEndian.Uint16(buf[offset:offset+2])
		case IE_DST_REF:
			rsp.Dst_id = binary.BigEndian.Uint16(buf[offset:offset+2])
		case IE_MSISDN:
			rsp.UpdateBundleUsageReq.Msisdn = string(buf[offset:offset+int(vallen)])
		case IE_SERVICE_TYPE:
			rsp.UpdateBundleUsageReq.ServiceType = buf[offset]
		case IE_ACCOUNT_ID:
			rsp.UpdateBundleUsageReq.AccountId = binary.BigEndian.Uint32(buf[offset:offset+4])
		case IE_PLAN_ID:
			rsp.UpdateBundleUsageReq.PlanId = binary.BigEndian.Uint32(buf[offset:offset+4])
		case IE_BUNDLE_ID:
			rsp.UpdateBundleUsageReq.BundleId = binary.BigEndian.Uint32(buf[offset:offset+4])
		case IE_PLAN_VALUE:
			rsp.UpdateBundleUsageReq.PlanValue = binary.BigEndian.Uint64(buf[offset:offset+8])
		case IE_PLAN_USED_VALUE:
			rsp.UpdateBundleUsageReq.PlanUsedValue = binary.BigEndian.Uint64(buf[offset:offset+8])
		case IE_SESS_UPDATE_TIME:
			rsp.UpdateBundleUsageReq.SessUpdateTime = binary.BigEndian.Uint32(buf[offset:offset+4])
		case IE_PLAN_VALUE_ADD_THIS_TIME:
			rsp.UpdateBundleUsageReq.PlanValueAddThisTime = binary.BigEndian.Uint64(buf[offset:offset+8])
		default:
		}
		offset += int(vallen)
	}

	l4g.RestLog.Debugf("decodeUpdateBundleUsageReq: %#v", rsp.UpdateSubsRsp)

	return 0
}

func Decode_udp_msg(buf []byte, msglen int, rsp *RestRsp) int {
	var offset int = 0
	
	if msglen <= 9 {
		return -1
	}
	
	rsp.MsgType = buf[offset]
	offset++
	switch (rsp.MsgType) {
	case REST_SEND_AUTHCODE_RSP:
		return decode_authcode_rsp(buf[1:], msglen-1, rsp)
	case REST_QUERY_USERDATA_RSP:
		return decode_query_userData_rsp(buf[1:], msglen-1, rsp)
	case REST_BUNDLE_SUBS_RSP:
		return decode_bundleSubs_rsp(buf[1:], msglen-1, rsp)
	case REST_RECHARGE_RSP:
		return decode_recharge_rsp(buf[1:], msglen-1, rsp)
	case REST_TRANSFER_RSP:
		return decode_transfer_rsp(buf[1:], msglen-1, rsp)
	case REST_QUERY_BALANCE_RSP:
		return decode_query_balance_rsp(buf[1:], msglen-1, rsp)
	case REST_CRM_CREATE_ACCT_RES:
		return decode_create_acct_rsp(buf[1:], msglen-1, rsp)
	case REST_CRM_UPDATE_SUBS_REQ:
		return decode_update_subs_req(buf[1:], msglen-1, rsp)
	case REST_CRM_UPDATE_SUBS_RES:
		return decode_update_subs_rsp(buf[1:], msglen-1, rsp)
	case REST_CRM_DELETE_SUBS_RES:
		return decode_delete_subs_rsp(buf[1:], msglen-1, rsp)
	case REST_CRM_UPDATE_PLAN_INFO_REQ:
		return decodeUpdateBundleUsageReq(buf[1:], msglen-1, rsp)
	default:
		return -1
	}
}

