package cn.jsms.api.common;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.regex.Pattern;

import cn.jiguang.common.connection.IHttpClient;
import cn.jiguang.common.connection.NettyHttpClient;
import cn.jiguang.common.utils.StringUtils;
import cn.jsms.api.account.AccountBalanceResult;
import cn.jsms.api.account.AppBalanceResult;
import cn.jsms.api.common.model.BatchSMSPayload;
import cn.jsms.api.common.model.BatchSMSResult;
import cn.jsms.api.schedule.model.ScheduleResult;
import cn.jsms.api.schedule.model.ScheduleSMSPayload;
import cn.jsms.api.schedule.model.ScheduleSMSResult;
import cn.jsms.api.sign.DefaultSignPayload;
import cn.jsms.api.sign.SignInfoResult;
import cn.jsms.api.sign.SignPayload;
import cn.jsms.api.sign.SignResult;
import cn.jsms.api.template.SendTempSMSResult;
import cn.jsms.api.template.TempSMSResult;
import cn.jsms.api.template.TemplatePayload;
import com.google.gson.JsonObject;

import cn.jiguang.common.ServiceHelper;
import cn.jiguang.common.utils.Preconditions;
import cn.jiguang.common.connection.HttpProxy;
import cn.jiguang.common.connection.NativeHttpClient;
import cn.jiguang.common.resp.APIConnectionException;
import cn.jiguang.common.resp.APIRequestException;
import cn.jiguang.common.resp.ResponseWrapper;
import cn.jsms.api.SendSMSResult;
import cn.jsms.api.ValidSMSResult;
import cn.jsms.api.common.model.SMSPayload;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLException;

public class SMSClient {

    private static String SMS_CODE = "code";
    private final String BOUNDARY = "========7d4a6d158c9";

    private String _baseUrl;
    private String _smsCodePath;
    private String _validPath;
    private String _voiceCodePath;
    private String _shortMsgPath;
    private String _schedulePath;
    private String _signPath;
    private String _signDefaultPath;
    private String _accountPath;
    private String _tempMsgPath;
    private IHttpClient _httpClient;
    private String _authCode;

    public SMSClient(String masterSecret, String appkey) {
        this(masterSecret, appkey, null, JSMSConfig.getInstance());
    }

    public SMSClient(String masterSecret, String appkey, HttpProxy proxy, JSMSConfig conf) {
        ServiceHelper.checkBasic(appkey, masterSecret);

        _baseUrl = (String) conf.get(JSMSConfig.API_HOST_NAME);
        _smsCodePath = (String) conf.get(JSMSConfig.CODE_PATH);
        _validPath = (String) conf.get(JSMSConfig.VALID_PATH);
        _voiceCodePath = (String) conf.get(JSMSConfig.VOICE_CODE_PATH);
        _shortMsgPath = (String) conf.get(JSMSConfig.SHORT_MESSAGE_PATH);
        _tempMsgPath = (String) conf.get(JSMSConfig.TEMPlATE_MESSAGE_PATH);
        _signPath = (String) conf.get(JSMSConfig.SIGN_PATH);
        _signDefaultPath = (String) conf.get(JSMSConfig.SIGN_DEFAULT_PATH);
        _schedulePath = (String) conf.get(JSMSConfig.SCHEDULE_PATH);
        _accountPath = (String) conf.get(JSMSConfig.ACCOUNT_PATH);
        String authCode = ServiceHelper.getBasicAuthorization(appkey, masterSecret);
        _authCode = authCode;
        this._httpClient = new NativeHttpClient(authCode, proxy, conf.getClientConfig());
    }

    /**
     * Send SMS verification code to mobile
     *
     * @param payload include two parameters: mobile number and templete id. The second parameter is optional.
     * @return return SendSMSResult which includes msg_id
     * @throws APIConnectionException connection exception
     * @throws APIRequestException    request exception
     */
    public SendSMSResult sendSMSCode(SMSPayload payload)
            throws APIConnectionException, APIRequestException {
        Preconditions.checkArgument(null != payload, "SMS payload should not be null");

        ResponseWrapper response = _httpClient.sendPost(_baseUrl + _smsCodePath, payload.toString());
        return SendSMSResult.fromResponse(response, SendSMSResult.class);
    }

    /**
     * Send SMS verification code to server, to verify if the code valid
     *
     * @param msgId The message id of the verification code
     * @param code  Verification code
     * @return return ValidSMSResult includes is_valid
     * @throws APIConnectionException connection exception
     * @throws APIRequestException    request exception
     */
    public ValidSMSResult sendValidSMSCode(String msgId, String code)
            throws APIConnectionException, APIRequestException {
        Preconditions.checkArgument(null != msgId, "Message id should not be null");
        Pattern codePattern = Pattern.compile("^[0-9]{6}");
        Preconditions.checkArgument(codePattern.matcher(code).matches(), "The verification code shoude be consist of six number");
        JsonObject json = new JsonObject();
        json.addProperty(SMS_CODE, code);

        ResponseWrapper response = _httpClient.sendPost(_baseUrl + _smsCodePath + "/" + msgId + _validPath, json.toString());
        return ValidSMSResult.fromResponse(response, ValidSMSResult.class);
    }

    /**
     * Send voice SMS verification code to mobile
     *
     * @param payload payload includes two parameters: mobile number and ttl(time to live),
     *                the second one is optional(if miss ttl, will use default value 60 seconds).
     * @return return SendSMSResult which includes msg_id
     * @throws APIConnectionException connection exception
     * @throws APIRequestException    request exception
     */
    public SendSMSResult sendVoiceSMSCode(SMSPayload payload)
            throws APIConnectionException, APIRequestException {
        Preconditions.checkArgument(null != payload, "SMS payload should not be null");

        ResponseWrapper response = _httpClient.sendPost(_baseUrl + _voiceCodePath, payload.toString());
        return SendSMSResult.fromResponse(response, SendSMSResult.class);
    }

    /**
     * Send template SMS to mobile
     *
     * @param payload payload includes mobile, temp_id and temp_para, the temp_para is a map,
     *                which's key is what you had set in jiguang portal
     * @return return SendSMSResult which includes msg_id
     * @throws APIConnectionException connection exception
     * @throws APIRequestException    request exception
     */
    public SendSMSResult sendTemplateSMS(SMSPayload payload)
            throws APIConnectionException, APIRequestException {
        Preconditions.checkArgument(null != payload, "SMS payload should not be null");

        ResponseWrapper response = _httpClient.sendPost(_baseUrl + _shortMsgPath, payload.toString());
        return SendSMSResult.fromResponse(response, SendSMSResult.class);
    }

    /**
     * Send a batch of template SMS
     *
     * @param payload BatchSMSPayload
     * @return BatchSMSResult
     * @throws APIConnectionException connect exception
     * @throws APIRequestException    request exception
     */
    public BatchSMSResult sendBatchTemplateSMS(BatchSMSPayload payload)
            throws APIConnectionException, APIRequestException {
        Preconditions.checkArgument(null != payload, "BatchSMSPayload should not be null");
        ResponseWrapper responseWrapper = _httpClient.sendPost(_baseUrl + _shortMsgPath + "/batch", payload.toString());
        return BatchSMSResult.fromResponse(responseWrapper, BatchSMSResult.class);
    }

    public void setHttpClient(IHttpClient client) {
        this._httpClient = client;
    }

    // 如果使用 NettyHttpClient,在发送请求后需要手动调用 close 方法
    public void close() {
        if (_httpClient != null && _httpClient instanceof NettyHttpClient) {
            ((NettyHttpClient) _httpClient).close();
        }
    }

    /**
     * Submit a mission that sending a template SMS with pointed schedule
     *
     * @param payload ScheduleSMSPayload
     * @return ScheduleResult which includes schedule_id
     * @throws APIConnectionException connect exception
     * @throws APIRequestException    request exception
     */
    public ScheduleResult sendScheduleSMS(ScheduleSMSPayload payload) throws APIConnectionException, APIRequestException {
        Preconditions.checkArgument(null != payload, "Schedule SMS payload should not be null");
        Preconditions.checkArgument(null != payload.getMobile(), "Mobile should not be null");
        Preconditions.checkArgument(StringUtils.isMobileNumber(payload.getMobile()), "Invalid mobile number");
        ResponseWrapper responseWrapper = _httpClient.sendPost(_baseUrl + _schedulePath, payload.toString());
        return ScheduleResult.fromResponse(responseWrapper, ScheduleResult.class);
    }

    /**
     * Modify SMS with schedule
     *
     * @param payload    ScheduleSMSPayload
     * @param scheduleId id
     * @return ScheduleResult which includes schedule_id
     * @throws APIConnectionException connect exception
     * @throws APIRequestException    request exception
     */
    public ScheduleResult updateScheduleSMS(ScheduleSMSPayload payload, String scheduleId)
            throws APIConnectionException, APIRequestException {
        Preconditions.checkArgument(null != payload, "Schedule SMS payload should not be null");
        Preconditions.checkArgument(null != scheduleId, "Schedule id should not be null");
        Preconditions.checkArgument(null != payload.getMobile(), "Mobile should not be null");
        Preconditions.checkArgument(StringUtils.isMobileNumber(payload.getMobile()), "Invalid mobile number");
        ResponseWrapper responseWrapper = _httpClient.sendPut(_baseUrl + _schedulePath + "/" + scheduleId, payload.toString());
        return ScheduleResult.fromResponse(responseWrapper, ScheduleResult.class);
    }

    /**
     * Submit a mission that sending a batch of SMS with schedule
     *
     * @param payload Payload should include sendTime and recipients
     * @return BatchSMSResult
     * @throws APIConnectionException connect exception
     * @throws APIRequestException    request exception
     */
    public BatchSMSResult sendBatchScheduleSMS(ScheduleSMSPayload payload)
            throws APIConnectionException, APIRequestException {
        Preconditions.checkArgument(null != payload, "Schedule SMS payload should not be null");
        Preconditions.checkArgument(null != payload.getRecipients(), "Recipients should not be null");
        ResponseWrapper responseWrapper = _httpClient.sendPost(_baseUrl + _schedulePath + "/batch", payload.toString());
        return BatchSMSResult.fromResponse(responseWrapper, BatchSMSResult.class);
    }

    /**
     * Update batch of SMS with schedule
     *
     * @param payload    ScheduleSMSPayload
     * @param scheduleId id
     * @return BatchSMSResult
     * @throws APIConnectionException connection exception
     * @throws APIRequestException    request exception
     */
    public BatchSMSResult updateBatchScheduleSMS(ScheduleSMSPayload payload, String scheduleId)
            throws APIConnectionException, APIRequestException {
        Preconditions.checkArgument(null != payload, "Schedule SMS payload should not be null");
        Preconditions.checkArgument(null != payload.getRecipients(), "Recipients should not be null");
        Preconditions.checkArgument(null != scheduleId, "Schedule id should not be null");
        ResponseWrapper responseWrapper = _httpClient.sendPut(_baseUrl + _schedulePath + "/batch/" + scheduleId, payload.toString());
        return BatchSMSResult.fromResponse(responseWrapper, BatchSMSResult.class);
    }

    /**
     * Get schedule SMS by scheduleId
     *
     * @param scheduleId id
     * @return ScheduleSMSResult
     * @throws APIConnectionException connection exception
     * @throws APIRequestException    request exception
     */
    public ScheduleSMSResult getScheduleSMS(String scheduleId) throws APIConnectionException, APIRequestException {
        Preconditions.checkArgument(null != scheduleId, "Schedule id should not be null");
        ResponseWrapper responseWrapper = _httpClient.sendGet(_baseUrl + _schedulePath + "/" + scheduleId);
        return ScheduleSMSResult.fromResponse(responseWrapper, ScheduleSMSResult.class);
    }

    /**
     * Delete schedule SMS by scheduleId
     *
     * @param scheduleId id
     * @return No content
     * @throws APIConnectionException connect exception
     * @throws APIRequestException    request exception
     */
    public ResponseWrapper deleteScheduleSMS(String scheduleId) throws APIConnectionException, APIRequestException {
        Preconditions.checkArgument(null != scheduleId, "Schedule id should not be null");
        return _httpClient.sendDelete(_baseUrl + _schedulePath + "/" + scheduleId);
    }

    /**
     * Get account's SMS balance
     *
     * @return AccountBalanceResult
     * @throws APIConnectionException connect exception
     * @throws APIRequestException    request exception
     */
    public AccountBalanceResult getSMSBalance() throws APIConnectionException, APIRequestException {
        ResponseWrapper responseWrapper = _httpClient.sendGet(_baseUrl + _accountPath + "/dev");
        return AccountBalanceResult.fromResponse(responseWrapper, AccountBalanceResult.class);
    }

    /**
     * Get app's SMS balance of an account
     *
     * @return AppBalanceResult
     * @throws APIConnectionException connect exception
     * @throws APIRequestException    request exception
     */
    public AppBalanceResult getAppSMSBalance() throws APIConnectionException, APIRequestException {
        ResponseWrapper responseWrapper = _httpClient.sendGet(_baseUrl + _accountPath + "/app");
        return AppBalanceResult.fromResponse(responseWrapper, AppBalanceResult.class);
    }

    //===============      Template API     =================

    /**
     * Create template sms.
     *
     * @param payload {@link TemplatePayload }
     * @return {@link SendTempSMSResult }, include temp_id
     * @throws APIConnectionException connect exception
     * @throws APIRequestException    request exception
     */
    public SendTempSMSResult createTemplate(TemplatePayload payload) throws APIConnectionException, APIRequestException {
        Preconditions.checkArgument(null != payload, "Template payload should not be null");
        ResponseWrapper responseWrapper = _httpClient.sendPost(_baseUrl + _tempMsgPath, payload.toString());
        return SendTempSMSResult.fromResponse(responseWrapper, SendTempSMSResult.class);
    }

    /**
     * update template sms. Template can be modified ONLY when status is not approved
     *
     * @param payload {@link TemplatePayload }
     * @param tempId  template id
     * @return {@link SendTempSMSResult }, include temp_id
     * @throws APIConnectionException connect exception
     * @throws APIRequestException    request exception
     */
    public SendTempSMSResult updateTemplate(TemplatePayload payload, int tempId) throws APIConnectionException, APIRequestException {
        Preconditions.checkArgument(null != payload, "Template payload should not be null");
        Preconditions.checkArgument(tempId > 0, "temp id is invalid");
        ResponseWrapper responseWrapper = _httpClient.sendPut(_baseUrl + _tempMsgPath + "/" + tempId, payload.toString());
        return SendTempSMSResult.fromResponse(responseWrapper, SendTempSMSResult.class);
    }

    /**
     * check template by id
     *
     * @param tempId necessary
     * @return {@link TempSMSResult}
     * @throws APIConnectionException connect exception
     * @throws APIRequestException    request exception
     */
    public TempSMSResult checkTemplate(int tempId) throws APIConnectionException, APIRequestException {
        Preconditions.checkArgument(tempId > 0, "temp id is invalid");
        ResponseWrapper responseWrapper = _httpClient.sendGet(_baseUrl + _tempMsgPath + "/" + tempId);
        return TempSMSResult.fromResponse(responseWrapper, TempSMSResult.class);
    }

    /**
     * Delete template by id
     *
     * @param tempId necessary
     * @return No content
     * @throws APIConnectionException connect exception
     * @throws APIRequestException    request exception
     */
    public ResponseWrapper deleteTemplate(int tempId) throws APIConnectionException, APIRequestException {
        Preconditions.checkArgument(tempId > 0, "temp id is invalid");
        return _httpClient.sendDelete(_baseUrl + _tempMsgPath + "/" + tempId);
    }

    /**
     * create sign
     * 其实两个接口可以合并 但没时间搞
     *
     * @param payload {@link SignPayload }
     * @return SignResult
     * @throws APIConnectionException connect exception
     * @throws APIRequestException    request exception
     */
    public SignResult createSign(SignPayload payload) throws APIConnectionException, APIRequestException {
        Preconditions.checkArgument(null != payload, "sign payload should not be null");
        Preconditions.checkArgument(payload.getType() > 0 && payload.getType() <= 7,
                "type should be between 1 and 7");
        Map<String, Object> params = new HashMap<String, Object>();
        params.put(SignPayload.getSIGN(), payload.getSign());
        if (!StringUtils.isEmpty(payload.getRemark())) {
            Preconditions.checkArgument(payload.getRemark().length() <= 100,
                    "remark too long");
            params.put(SignPayload.getREMARK(), payload.getRemark());
        }
        params.put(SignPayload.getTYPE(), payload.getType());
        Map<String, byte[]> fileParams = new HashMap<String, byte[]>();
        File[] images = payload.getImages();
        if (images != null && images.length > 0) {
            for (File file : payload.getImages()) {
                fileParams.put(file.getName(), getBytes(file));
            }
        }
        String url = _baseUrl + _signPath;
        try {
            ResponseWrapper wrapper = doPostSign(url, params, fileParams, SignPayload.getIMAGES());
            if (wrapper.responseCode != 200) {
                throw new APIRequestException(wrapper);
            }
            return SignResult.fromResponse(wrapper, SignResult.class);
        } catch (IOException e) {
            e.printStackTrace();
            throw new IllegalArgumentException("fail to creat sign");
        }
    }

    /**
     * update sign
     *
     * @param payload {@link SignPayload }
     * @param signId necessary
     * @return SignResult
     * @throws APIConnectionException connect exception
     * @throws APIRequestException    request exception
     */
    public SignResult updateSign(SignPayload payload, int signId) throws APIConnectionException, APIRequestException {
        Preconditions.checkArgument(null != payload, "sign payload should not be null");
        Preconditions.checkArgument(payload.getType() > 0 && payload.getType() <= 7,
                "type should be between 1 and 7");

        Map<String, Object> params = new HashMap<String, Object>();
        params.put(SignPayload.getSIGN(), payload.getSign());
        if (!StringUtils.isEmpty(payload.getRemark())) {
            Preconditions.checkArgument(payload.getRemark().length() <= 100,
                    "remark too long");
            params.put(SignPayload.getREMARK(), payload.getRemark());
        }
        params.put(SignPayload.getTYPE(), payload.getType());
        Map<String, byte[]> fileParams = new HashMap<String, byte[]>();
        File[] images = payload.getImages();
        if (images != null && images.length > 0) {
            for (File file : payload.getImages()) {
                fileParams.put(file.getName(), getBytes(file));
            }
        }
        String url = _baseUrl + _signPath + "/" + signId;
        try {
            ResponseWrapper wrapper = doPostSign(url, params, fileParams, SignPayload.getIMAGES());
            if (wrapper.responseCode != 200) {
                throw new APIRequestException(wrapper);
            }
            return SignResult.fromResponse(wrapper, SignResult.class);
        } catch (IOException e) {
            e.printStackTrace();
            throw new IllegalArgumentException("fail to update sign");
        }
    }

    /**
     * delete sig by id
     *
     * @param signId necessary
     * @return ResponseWrapper
     * @throws APIConnectionException connect exception
     * @throws APIRequestException    request exception
     */
    public ResponseWrapper deleteSign(int signId) throws APIConnectionException, APIRequestException {
        Preconditions.checkArgument(signId > 0, "sign id is invalid");
        return _httpClient.sendDelete(_baseUrl + _signPath + "/" + signId);
    }

    /**
     * get sign by id
     *
     * @param signId necessary
     * @return SignInfoResult
     * @throws APIConnectionException connect exception
     * @throws APIRequestException    request exception
     */
    public SignInfoResult checkSign(int signId) throws APIConnectionException, APIRequestException {
        Preconditions.checkArgument(signId > 0, "sign id is invalid");
        ResponseWrapper responseWrapper = _httpClient.sendGet(_baseUrl + _signPath + "/" + signId);
        return SignInfoResult.fromResponse(responseWrapper, SignInfoResult.class);
    }

//    /**
//     * set default sign  Discard
//     *
//     * @param payload
//     * @return
//     * @throws APIConnectionException
//     * @throws APIRequestException
//     */
//    public ResponseWrapper setDefaultSign(DefaultSignPayload payload) throws APIConnectionException, APIRequestException {
//        Preconditions.checkArgument(payload != null, "sign should not be null");
//        ResponseWrapper responseWrapper = _httpClient.sendPost(_baseUrl + _signDefaultPath, payload.toString());
//        return responseWrapper;
//    }

    /**
     * post sign
     *
     * @param strUrl url
     * @param params param
     * @param fileParams fileParam
     * @param fileName fileName
     * @return ResponseWrapper
     * @throws IOException connect exception
     */
    public ResponseWrapper doPostSign(String strUrl, Map<String, Object> params, Map<String,
            byte[]> fileParams, String fileName) throws IOException {
        ResponseWrapper wrapper = new ResponseWrapper();
        String TWO_HYPHENS = "--";
        String LINE_END = "\r\n";

        URL url = new URL(strUrl);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();//得到connection对象
        /************************************设置请求头*************************************************/
        connection.setRequestMethod("POST");    //设置请求方式为POST
        connection.setDoOutput(true);           //允许写出
        connection.setDoInput(true);            //允许读入
        connection.setUseCaches(false);         //不使用缓存
        connection.setRequestProperty("Charset", "utf-8");//编码格式
        connection.setRequestProperty("Authorization", _authCode);
        connection.setRequestProperty("Content-Type", "multipart/form-data ; boundary=" + BOUNDARY); // 设置发送数据的格式(form-data格式)   //boundary为头部分隔符,头部拼接时需要分隔符。例如下面的有多个"Content-Disposition"拼接时需要用到此分隔符
        connection.connect(); //连接
        /************************************输出流,写数据,start*************************************************/
        DataOutputStream out = new DataOutputStream(connection.getOutputStream());//获得输出流对象
        StringBuffer strBufparam = new StringBuffer();
        Iterator it = params.entrySet().iterator();
        while (it.hasNext()) {
            //封装键值对数据
            Map.Entry<String, String> entry = (Map.Entry) it.next();
            String key = entry.getKey();
            String value = String.valueOf(entry.getValue());

            strBufparam.append(TWO_HYPHENS);
            strBufparam.append(BOUNDARY);
            strBufparam.append(LINE_END);//"--" + BOUNDARY + "\r\n"
            strBufparam.append("Content-Disposition: form-data; name=\"" + key + "\"");
            strBufparam.append(LINE_END);
            strBufparam.append(LINE_END);
            strBufparam.append(value);
            strBufparam.append(LINE_END);
        }
        out.write(strBufparam.toString().getBytes("utf-8"));
        //写入图片参数
        if (fileParams != null && fileParams.size() > 0) {
            Iterator fileIt = fileParams.entrySet().iterator();
            while (fileIt.hasNext()) {
                Map.Entry<String, byte[]> fileEntry = (Map.Entry<String, byte[]>) fileIt.next();
                //拼接文件的参数
                StringBuffer strBufFile = new StringBuffer();
                strBufFile.append(TWO_HYPHENS);
                strBufFile.append(BOUNDARY);
                strBufFile.append(LINE_END);
                strBufFile.append("Content-Disposition: form-data; name=\"" + fileName + "\"; filename=\"" + fileEntry.getKey() + "\"");// filename:参数名。fileEntry.getKey():文件名称
                strBufFile.append(LINE_END);
                strBufFile.append("Content-Type:application/octet-stream");
                strBufFile.append(LINE_END);
                strBufFile.append(LINE_END);
                out.write(strBufFile.toString().getBytes("utf-8"));
                out.write(fileEntry.getValue());//文件 (此参数之前调用了本页面的重写方法getBytes(File f),将文件转换为字节数组了 )
                out.write((LINE_END).getBytes());
            }
        }

        //写入标记结束位
        byte[] endData = (TWO_HYPHENS + BOUNDARY + TWO_HYPHENS + LINE_END).getBytes();//写结束标记位
        out.write(endData);
        out.flush();
        out.close();

        /************************************输出流,写数据完成end*************************************************/
        int code = connection.getResponseCode(); //获得响应码(200为成功返回)
        InputStream in;
        try {
            if (code == HttpURLConnection.HTTP_OK) {
                in = connection.getInputStream(); //获取响应流
            } else {
                in = connection.getErrorStream(); //获取响应流
            }
        } catch (SSLException e) {
            e.printStackTrace();
            throw new IllegalArgumentException("fail to get inputStream");
        }
        /**********读取返回的输入流信息**************/
        byte[] bytes;
        ByteArrayOutputStream baout = new ByteArrayOutputStream();
        byte[] buff = new byte[1024];
        if (in != null) {
            int len;
            while ((len = in.read(buff)) != -1) {
                baout.write(buff, 0, len);
            }
            in.close();
        }
        bytes = baout.toByteArray();
        String ret = new String(bytes, "utf-8");
        /**********封装返回的输入流信息**************/
        String responseContentStr = ret;
        wrapper.responseCode = code;
        wrapper.responseContent = responseContentStr;
        return wrapper;
    }

    /**
     * 将文件转换为byte数组
     *
     * @param f file
     * @return byte[] bytes
     */
    public static byte[] getBytes(File f) {
        try {
            InputStream in = new FileInputStream(f);
            ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
            byte[] b = new byte[1024];
            int n;
            while ((n = in.read(b)) != -1)
                out.write(b, 0, n);
            in.close();
            out.close();
            return out.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
            throw new IllegalArgumentException("File is invalid, please check again");
        }
    }


}