package com.imofan.android.pns;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.*;
import android.telephony.TelephonyManager;
import com.imofan.android.basic.MFStatInfo;
import com.imofan.android.basic.Mofang;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.jivesoftware.smack.*;
import org.jivesoftware.smack.packet.Message;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.*;
import java.lang.reflect.Method;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.Deflater;

/**
 *
 */
public class PNService extends Service {
    private final static String LOG_TAG = "Mofang_PNS_PNService";

    //PUBLISH CHECK
//    public final static boolean DEBUG = true;   //SDK调试开关
    public final static boolean DEBUG = false;   //SDK调试开关
    public static boolean debug = false;    //API调用调试开关

    private final static int VERSION = 101;     //SDK版本号

    private static PNService service;
    private static PNBroadcastReceiver receiver;

    private static PowerManager.WakeLock wakeLock;
//    private static WifiManager.WifiLock wifiLock;

    //PUBLISH CHECK
    private final static String MOFANG_TOKEN_COLLECTOR = "http://c.imofan.com/";
    final static String PUSHER_HOST = "gpns.imofan.com";
    //    private final static String PUSHER_HOST = "shdev.pclady.com.cn";
//    private final static String PUSHER_HOST = "192.168.199.252";
    private final static int PUSHER_PORT = 5222;
    private final static String PNS_HOST = "gpns.imofan.com:8080";
    //    private final static String PNS_HOST = "shdev.pclady.com.cn:8080/apns";
    private final static String PNS_RECEIVER_REGISTER = "http://" + PNS_HOST + "/receiver/register";
    private final static String PNS_APP_TOKEN = "http://" + PNS_HOST + "/app/token";

    //PUBLISH CHECK
    public final static String SERVICE_NAME = "Mofang.PNS";
    public final static String SERVICE_ACTION = "com.imofan.pns.action.START";
    private final static int SERVICE_CHECK_INTERVAL = 300;   //推送服务检查周期，单位：秒
    final static int CPU_ACTIVE_TIME = 10;
    final static int KEEP_ALIVE_INTERVAL = 60;
    final static int PACKET_REPLY_TIMEOUT = 40;
    private static PendingIntent serviceCheckIntent = null;

    private static boolean screenOn = true;    //屏幕状态
    private static boolean powerConnected = false;  //是否处于充电状态
    private static boolean networkChanged = false;  //网络发生了变化

    //PUBLISH CHECK
//    private static long lastConnectTime;
//    private final static int RECONNECTION_INTERVAL = 600;    //单位：秒
//    private final static int RECONNECTION_ACTIVE = 10;    //单位：秒

    private static SharedPreferences sp = null;
    private static SharedPreferences.Editor spEditor = null;
    private final static String SP_FILE = "mofang_pns";
    private final static String INFO_UDID = "udid";
    private final static String INFO_PASSWORD = "password";
    private final static String INFO_TOKEN = "token";
    private final static String INFO_SENT = "sent";
    private final static String INFO_USE_MOFANG = "use_mofang";
    private final static String INFO_LISTENER = "listener";
    private final static String INFO_STATUS = "status";

    private static String appkey;
    private static String devinfo;
    static String udid;
    static String password;
    private static String token;

    private static Connection connection = null;

    private static DefaultHttpClient httpClient;
    private final static String USER_AGENT = "imofan pns client";
    private final static String ACCEPT_ENCODING = "gzip, deflate";

    private static XmppManager xmppManager;

    // some stuff for the async service implementation - borrowed heavily from
    // the standard IntentService, but that class doesn't offer fine enough
    // control for "foreground" services.
    private static volatile Looper serviceLooper;
    private static volatile ServiceHandler serviceHandler;
    private long handlerThreadId;
    private static Handler delayedDisconnectHandler;

    private static long lastReadTime = System.currentTimeMillis();

    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(android.os.Message msg) {
            try {
                int id = msg.arg1;

                // ensure XMPP manager is setup (but not yet connected)
                if (xmppManager == null) {
                    xmppManager = XmppManager.getInstance(PNService.this);
                }

                if (Thread.currentThread().getId() != handlerThreadId) {
                    return;
                }

                if(isNetworkAvailable(service)) {
                    if(!networkChanged && (screenOn || powerConnected)) {
                        checkHeartbeat();
                    } else {
                        xmppManager.xmppRequestStateChange(XmppManager.DISCONNECTED);
                        networkChanged = false;
                        if(!screenOn && !powerConnected) {
                            acquireWakeLock(CPU_ACTIVE_TIME);
                        }
                    }
                    xmppManager.xmppRequestStateChange(XmppManager.CONNECTED);
                } else {
                    xmppManager.xmppRequestStateChange(XmppManager.DISCONNECTED);
                }

                // stop the service if we are disconnected (but stopping the service
                // doesn't mean the process is terminated - onStart can still happen.)
                if (getConnectionStatus() == XmppManager.DISCONNECTED) {
                    if (stopSelfResult(id)) {
                        PNLog.i(LOG_TAG, "service is stopping because we are disconnected and no pending intents exist");
                    } else {
                        PNLog.i(LOG_TAG, "we are disconnected, but more pending intents to be delivered - service will not stop");
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public static synchronized void start(
            final Context context, final Class listenerClass, final boolean useMofangNotification) {
        if(DEBUG) {
            debug = true;
            PNLog.d(LOG_TAG, "[start]");
        }

        try {
            //启动服务检查定时器
            startCheckAlarm(context);

            //初始化
            init(context, listenerClass, useMofangNotification);

            new Thread(new Runnable() {
                public void run() {
                    if(isNetworkAvailable(context)) {
                        //注册设备帐户并获取推送token
                        if(udid == null || udid.trim().length() == 0
                                || password == null || password.trim().length() == 0
                                || token == null || token.trim().length() == 0) {
                            //注册设备账户
                            register(context);
                            if((token == null || token.trim().length() == 0)
                                    && udid != null && udid.trim().length() > 0
                                    && password != null && password.trim().length() > 0) {
                                //获取推送token
                                updateToken(context);
                            }
                        }

                        //发送token到应用服务器
                        sendTokenToAppServer(context);
                    }

                    //启动推送后台服务，若其它app已启动该服务，则跳过
                    if(appkey != null && appkey.trim().length() > 0
                            && devinfo != null && devinfo.trim().length() > 0
                            && udid != null && udid.trim().length() > 0
                            && password != null && password.trim().length() > 0) {
                        Intent serviceIntent = new Intent(SERVICE_ACTION);
                        serviceIntent.putExtra("version", VERSION);
                        serviceIntent.putExtra("appkey", appkey);
                        serviceIntent.putExtra("devinfo", devinfo);
                        serviceIntent.putExtra("udid", udid);
                        serviceIntent.putExtra("password", password);
                        serviceIntent.putExtra("debug", debug);
                        context.startService(serviceIntent);
                    }
                }
            }).start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();

        try {
            PowerManager powerManager = (PowerManager)(this.getSystemService(Context.POWER_SERVICE));

            if(powerManager != null) {
                wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, LOG_TAG);
            }

    //        WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
    //        if (wifiManager != null) {
    //            wifiLock = wifiManager.createWifiLock("Mofang PNS wifi lock");
    //        }

    //        if(wakeLock != null) {
    //            wakeLock.acquire();
    //        }

            service = this;
            if(DEBUG) {
                PNLog.init(this);
            }

            receiver = new PNBroadcastReceiver();
            IntentFilter filter = new IntentFilter();
            filter.addAction("android.intent.action.SCREEN_ON");
            filter.addAction("android.intent.action.SCREEN_OFF");
            filter.addAction("android.intent.action.ACTION_POWER_CONNECTED");
            filter.addAction("android.intent.action.ACTION_POWER_DISCONNECTED");
            filter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
            registerReceiver(receiver, filter);

            // Start a new thread for the service
            HandlerThread thread = new HandlerThread(SERVICE_NAME);
            thread.start();
            handlerThreadId = thread.getId();
            serviceLooper = thread.getLooper();
            serviceHandler = new ServiceHandler(serviceLooper);
            delayedDisconnectHandler = new Handler(serviceLooper);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        try {
            if(intent != null) {
                Bundle bundle = intent.getExtras();
                int version = bundle.getInt("version");
                appkey = bundle.getString("appkey");
                devinfo = bundle.getString("devinfo");
                udid = bundle.getString("udid");
                password = bundle.getString("password");
                debug = bundle.getBoolean("debug");

                if(version > VERSION) {
                    //TODO: 版本策略仍有问题，需改进
                    PNLog.d(LOG_TAG, "SDK version is old, service will be stop.");
                    this.stopSelf();
                } else {
                    //检查到推送服务器的连接情况
                    android.os.Message msg = serviceHandler.obtainMessage();
                    msg.arg1 = startId;
                    msg.obj = intent;
                    serviceHandler.sendMessage(msg);
                }
            } else {
                this.stopSelf();
            }
        } catch(Exception e) {
            e.printStackTrace();
        }

        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        // If the _xmppManager is non-null, then our service was "started" (as
        // opposed to simply "created" - so tell the user it has stopped.
        try {
            releaseWakeLock();
            if (xmppManager != null) {
                xmppManager.xmppRequestStateChange(XmppManager.DISCONNECTED);
                xmppManager = null;
                xmppManager.mSmackAndroid.exit();
            }
            serviceLooper.quit();
            unregisterReceiver(receiver);
        } catch (Exception e) {
            e.printStackTrace();
        }
        super.onDestroy();
    }

    private static void init(Context context, Class listenerClass, boolean useMofangNotification) {
        //初始化
        if(httpClient == null) {
            if(DEBUG) {
                debug();
            }

            //初始化HttpClient
            HttpParams httpParams = new BasicHttpParams();
            SchemeRegistry schReg = new SchemeRegistry();
            schReg.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
            schReg.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
            ClientConnectionManager connectionManager = new ThreadSafeClientConnManager(httpParams, schReg);
            httpClient = new DefaultHttpClient(connectionManager, httpParams);

            //初始化本地SharePreferences
            sp = context.getSharedPreferences(SP_FILE, MODE_PRIVATE);
            spEditor = sp.edit();

            //获取缓存的appkey
            appkey = Mofang.getAppKey(context);
            PNLog.d(LOG_TAG, "appkey = " + appkey);

            //获取缓存的设备硬件信息
            devinfo = getDeviceInfo(context);
            PNLog.d(LOG_TAG, "devinfo = " + devinfo);

            //读取缓存的推送授权信息
            udid = sp.getString(INFO_UDID, null);
            password = sp.getString(INFO_PASSWORD, null);
            token = sp.getString(INFO_TOKEN, null);
            PNLog.d(LOG_TAG, "udid[cached] = " + udid);
            if(DEBUG) {
                PNLog.d(LOG_TAG, "password[cached] = " + password);
            }
            PNLog.d(LOG_TAG, "token[cached] = " + token);

            if(listenerClass != null) {
                spEditor.putString(INFO_LISTENER, listenerClass.getName());
                spEditor.commit();
                PNLog.d(LOG_TAG, "notificationListenerClass = " + listenerClass.getName());
            }

            if(useMofangNotification) {
                spEditor.putBoolean(INFO_USE_MOFANG, true);
                spEditor.commit();
                PNLog.d(LOG_TAG, "useMofangNotification = " + useMofangNotification);
            }
        }
    }

    static void processMessage(Message message) {
        PNLog.d(LOG_TAG, "received message: " + message.getBody());
        try {
            Intent intent = new Intent();
            intent.setAction(PNBroadcastReceiver.ACTION_NOTIFICATION);
            JSONObject json = new JSONObject(message.getBody());
            intent.putExtra("pushid", json.optString("pushid", null));
            intent.putExtra("token", json.optString("token", null));
            intent.putExtra("content", json.optString("content", null));
            service.sendBroadcast(intent);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void startCheckAlarm(Context context) {
        //设置后台服务定时启动
        AlarmManager alarmManager = (AlarmManager) context.getSystemService("alarm");
        //取消前面之前已经过时的 定时器
        if(serviceCheckIntent != null) {
            alarmManager.cancel(serviceCheckIntent);
        }
        Intent broadcastIntent = new Intent(context, PNBroadcastReceiver.class);
        serviceCheckIntent = PendingIntent.getBroadcast(
                context.getApplicationContext(), 0, broadcastIntent, 0);

        //设置新的定时器：类型，开始时间，间隔时间，定时触发的intent
        alarmManager.setRepeating(
                AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + SERVICE_CHECK_INTERVAL * 1000,
                SERVICE_CHECK_INTERVAL * 1000, serviceCheckIntent);
//        alarmManager.set(AlarmManager.RTC_WAKEUP,
//                System.currentTimeMillis() + SERVICE_CHECK_INTERVAL * 1000, serviceCheckIntent);
    }

    //设备注册
    private static void register(Context context) {
        if(appkey != null && appkey.trim().length() > 0 && devinfo != null && devinfo.trim().length() > 0) {
            HttpPost request = new HttpPost(PNS_RECEIVER_REGISTER);
            request.addHeader("User-Agent", USER_AGENT);
            request.addHeader("Accept-Encoding", ACCEPT_ENCODING);

            List<NameValuePair> params = new ArrayList<NameValuePair>();
            params.add(new BasicNameValuePair("appkey", appkey));
            params.add(new BasicNameValuePair("devinfo", devinfo));

//            acquireWakeLock(context);
            try {
                HttpEntity httpEntity = new UrlEncodedFormEntity(params, HTTP.UTF_8);
                request.setEntity(httpEntity);

                HttpResponse response = httpClient.execute(request);
                if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                    String responseStr = EntityUtils.toString(response.getEntity());
                    if(DEBUG) {
                        PNLog.d(LOG_TAG, "[register]response: " + responseStr);
                    }
                    if(responseStr != null && responseStr.trim().length() > 0) {
                        JSONObject responseJson = new JSONObject(responseStr);
//                        {
//                            "stat": 1,         //取值为：1 注册成功，0 已注册过，-1 注册失败
//                            "udid": "f432e552242535353",
//                            "pwd":  "12345678",
//                            "info": "注册失败时的额外信息"
//                        }
                        int status = responseJson.optInt("stat", -1);
                        if(status >= 0) {   //注册成功
                            udid = responseJson.optString("udid", null);
                            password = responseJson.optString("pwd", null);
                            if(udid != null && udid.trim().length() > 0
                                    && password != null && password.trim().length() > 0) {
                                spEditor.putString(INFO_UDID, udid);
                                spEditor.putString(INFO_PASSWORD, password);
                                spEditor.commit();
                            }
                            if(debug) {
                                String log = "device register success: udid = " + udid;
                                if(DEBUG) {
                                    log += ", password = " + password;
                                }
                                PNLog.d(LOG_TAG, log);
                            }
                        } else {
                            PNLog.e(LOG_TAG, "device register failed: " + responseJson.optString("info", ""));
                        }
                    }
                } else {
                    PNLog.d(LOG_TAG, "device register failed: http status code = "
                            + response.getStatusLine().getStatusCode());
                }
            } catch (UnsupportedEncodingException e) {
                PNLog.e(LOG_TAG, "UnsupportedEncodingException");
                e.printStackTrace();
            } catch (ClientProtocolException e) {
                PNLog.e(LOG_TAG, "ClientProtocolException");
                e.printStackTrace();
            } catch (IOException e) {
                PNLog.e(LOG_TAG, "IOException");
                e.printStackTrace();
            } catch (JSONException e) {
                PNLog.e(LOG_TAG, "JSONException");
                e.printStackTrace();
            } finally {
//                releaseWakeLock();
            }
        }
    }

    private static void updateToken(Context context) {
        if(appkey != null && appkey.trim().length() > 0
                && udid != null && udid.trim().length() > 0
                && password != null && password.trim().length() > 0) {
            HttpPost request = new HttpPost(PNS_APP_TOKEN);
            request.addHeader("User-Agent", USER_AGENT);
            request.addHeader("Accept-Encoding", ACCEPT_ENCODING);

            List<NameValuePair> params = new ArrayList<NameValuePair>();
            params.add(new BasicNameValuePair("appkey", appkey));
            params.add(new BasicNameValuePair("udid", udid));
            params.add(new BasicNameValuePair("pwd", password));

//            acquireWakeLock(context);
            try {
                HttpEntity httpEntity = new UrlEncodedFormEntity(params, HTTP.UTF_8);
                request.setEntity(httpEntity);

                HttpResponse response = httpClient.execute(request);
                if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                    String responseStr = EntityUtils.toString(response.getEntity());
                    if(DEBUG) {
                        PNLog.d(LOG_TAG, "[updateToken]responseStr(token) = " + responseStr);
                    }
                    if(responseStr != null && responseStr.trim().length() > 0) {
                        JSONObject responseJson = new JSONObject(responseStr);
//                            {
//                                "stat": 1,    //取值为：1 Token分配成功，-1 分配失败
//                                "token": "64tru67554fdwe12d",
//                                "info": "分配token失败时的额外信息"
//                            }
                        int status = responseJson.optInt("stat", -1);
                        if(status == 1) {   //Token分配成功
                            String newToken = responseJson.optString("token", null);
                            if(newToken != null && newToken.trim().length() > 0 && !newToken.equals(token)) {
                                token = newToken;
                                spEditor.putString(INFO_TOKEN, newToken);
                                spEditor.putBoolean(INFO_SENT, false);
                                spEditor.commit();
                            }
                            PNLog.d(LOG_TAG, "get push token success: " + newToken);
                        } else {
                            PNLog.e(LOG_TAG, "get push token failed: " + responseJson.optString("info", ""));
                        }
                    }
                } else {
                    PNLog.d(LOG_TAG, "get push token failed: http status code = "
                            + response.getStatusLine().getStatusCode());
                }
            } catch (UnsupportedEncodingException e) {
                PNLog.e(LOG_TAG, "UnsupportedEncodingException");
                e.printStackTrace();
            } catch (ClientProtocolException e) {
                PNLog.e(LOG_TAG, "ClientProtocolException");
                e.printStackTrace();
            } catch (IOException e) {
                PNLog.e(LOG_TAG, "IOException");
                e.printStackTrace();
            } catch (JSONException e) {
                PNLog.e(LOG_TAG, "JSONException");
                e.printStackTrace();
            } finally {
//                releaseWakeLock();
            }
        }
    }

    //发送token到应用服务器
    private static void sendTokenToAppServer(Context context) {
        boolean tokenSent = sp.getBoolean(INFO_SENT, true);
        if(!tokenSent) {
            tokenSent = true;

            //发送到第三方应用服务器
            Class cacheListenerClass = null;
            String listenerName = sp.getString(INFO_LISTENER, null);
            if(listenerName != null && listenerName.trim().length() > 0) {
                try {
                    cacheListenerClass = Class.forName(listenerName);
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }
            if(cacheListenerClass != null) {
                PNListener listener = null;
                try {
                    listener = (PNListener)cacheListenerClass.newInstance();
                    listener.onTokenUpdated(context, token);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                }
            }

            boolean useMofang = sp.getBoolean(INFO_USE_MOFANG, false);
            if(useMofang) {
                //发送token到魔方服务器 TODO: devId经常无法获取
                String devId = Mofang.getDevId(context);
                if(devId != null && devId.trim().length() > 0
                        && token != null && token.trim().length() > 0) {
                    tokenSent = sendTokenToMofang(context, devId, token);
                }
            }

            if(tokenSent) {
                spEditor.putBoolean(INFO_SENT, true);
                spEditor.commit();
            }
        }
    }

    private static boolean sendTokenToMofang(Context context, String devId, String token) {
        HttpURLConnection connection = null;
        Deflater deflater = null;
        DataOutputStream output = null;

//        acquireWakeLock(context);

        try {
//            "dev_id":"102f4eab159c",       //设备ID,每次请求必须带过去
//        　　"token":"6D55EE867984F6138F614484A4F635E682AC612F771B0697DE65047C7CE858AE",       //apns token,64位16进制字符串
//            "os_ver":"5.0.1",           //设备版本
//            "app_ver":"1.0.1",          //应用版本
//            "model":"iphone4,1",       //设备型号
            //生成数据
            JSONObject json = new JSONObject();
            json.put(MFStatInfo.KEY_DEV_ID, devId);
            json.put("apns", token);
            JSONArray updateArray = new JSONArray();
            updateArray.put("apns");
            json.put("update", updateArray);
            json.put("send_time", System.currentTimeMillis()/1000);

            //压缩数据
            byte[] input = json.toString().getBytes("utf-8");
            deflater = new Deflater();
            deflater.setInput(input);
            deflater.finish();
            int size = 0;
            byte[] byteData = new byte[0];
            byte[] buf = new byte[128];
            while (!deflater.finished()) {
                int byteCount = deflater.deflate(buf);
                byte[] temp = new byte[byteData.length + byteCount];
                for(int i=0; i<byteData.length; i++) {
                    temp[i] = byteData[i];
                }
                for(int i=0; i<byteCount; i++) {
                    temp[byteData.length + i] = buf[i];
                }
                byteData = temp;
                size += byteCount;
            }

            //发送数据
            URL url = new URL(MOFANG_TOKEN_COLLECTOR + Mofang.getAppKey(context));
            connection = (HttpURLConnection) url.openConnection();
            connection.setDoOutput(true);
            connection.setDoInput(true);
            connection.setReadTimeout(20000);
            connection.setConnectTimeout(20000);
            connection.setRequestMethod("POST");
            connection.setUseCaches(false);
            connection.setRequestProperty("Connection", "Keep-Alive");
            connection.setRequestProperty("Content-Type", "application/octet-stream");
            connection.connect();
            output = new DataOutputStream(connection.getOutputStream());
            output.write(byteData);
            output.flush();
            int httpCode = connection.getResponseCode();

            if(httpCode == HttpStatus.SC_OK) {
                PNLog.d(LOG_TAG, "send token to Mofang success");
                StringBuilder sb = new StringBuilder();
                BufferedReader reader = null;
                try {
                    reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                    String line = null;
                    while ((line = reader.readLine()) != null) {
                        sb.append(line).append("\n");
                    }
                } catch (IOException e) {
                    PNLog.e(LOG_TAG, "IOException");
                    e.printStackTrace();
                } finally {
                    if(reader != null) {
                        try {
                            reader.close();
                        } catch (IOException e) {
                            PNLog.e(LOG_TAG, "IOException");
                            e.printStackTrace();
                        }
                    }
                }
                String response = sb.toString();
                if(DEBUG) {
                    PNLog.d(LOG_TAG, "Mofang server response: " + response);
                }

                if(response.contains("HTTPSQS_PUT_OK")) {
                    return true;
                } else {
                    PNLog.d(LOG_TAG, "send token to Mofang failed: " + response);
                }
            } else {
                PNLog.d(LOG_TAG, "send token to Mofang failed: http status code = " + httpCode);
            }
        } catch (UnsupportedEncodingException e) {
            PNLog.e(LOG_TAG, "UnsupportedEncodingException");
            e.printStackTrace();
        } catch (MalformedURLException e) {
            PNLog.e(LOG_TAG, "MalformedURLException");
            e.printStackTrace();
        } catch (ProtocolException e) {
            PNLog.e(LOG_TAG, "ProtocolException");
            e.printStackTrace();
        } catch (IOException e) {
            PNLog.e(LOG_TAG, "IOException");
            e.printStackTrace();
        } catch (JSONException e) {
            PNLog.e(LOG_TAG, "JSONException");
            e.printStackTrace();
        } finally {
//            releaseWakeLock();
            if(output != null) {
                try {
                    output.close();
                } catch (IOException e) {
                    PNLog.e(LOG_TAG, "IOException");
                    e.printStackTrace();
                }
            }
            if(deflater != null) {
                deflater.end();
            }
            if(connection != null) {
                connection.disconnect();
            }
        }

        return false;
    }

    //获取硬件信息
    private static String getDeviceInfo(Context context) {
        //获取设备ID
        String deviceId = "";
        try {
            TelephonyManager telephonyManager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
            deviceId = telephonyManager.getDeviceId().toLowerCase();
            if(deviceId.equals("000000000000000")) {
                deviceId = "";
            }
        } catch (Exception ignored) {

        }

        //获取WiFi Mac地址
        WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
        WifiInfo info = wifi.getConnectionInfo();
        String mac = (info == null) ? "" : (info.getMacAddress() == null ? "" : info.getMacAddress())
                .replaceAll(":", "").toLowerCase();

        //获取设备序列号
        String serialnum = "";
        try {
            Class<?> c = Class.forName("android.os.SystemProperties");
            Method get = c.getMethod("get", String.class, String.class );
            serialnum = (String)(get.invoke(c, "ro.serialno", ""));
        } catch (Exception ignored) {

        }

        //生成身份指纹
        String sum = deviceId + "-" + mac + "-" + serialnum;
        if(sum.length() <= 2) {
            sum = "random-" + Build.MODEL + "-" + System.currentTimeMillis() + "-" + Math.random();
        }

        //PUBLISH CHECK
        return sum;
//        return "test201208281601";
    }

    private static boolean isNetworkAvailable(Context context) {
        boolean netWorkStatus = false;

        ConnectivityManager connManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if(connManager.getActiveNetworkInfo()!=null){
            netWorkStatus = connManager.getActiveNetworkInfo().isAvailable();
        }

        return netWorkStatus;
    }

    public static void disconnect() {
//        if(connection != null) {
//            if(connection.isConnected()) {
//                connection.disconnect();
//            }
//            connection = null;
//        }
        if(xmppManager != null) {
            xmppManager.xmppRequestStateChange(XmppManager.DISCONNECTED);
        }
    }

    public static String getToken(Context context) {
        init(context, null, false);
        return token;
    }

    public static String getUdid(Context context) {
        init(context, null, false);
        return udid;
    }

    static PNListener getNotificationListener(Context context) {
        init(context, null, false);
        PNListener listener = null;
        String listenerName = sp.getString(INFO_LISTENER, null);
        if(listenerName != null && listenerName.trim().length() > 0) {
            try {
                listener = (PNListener)Class.forName(listenerName).newInstance();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        return listener;
    }

    public static void debug() {
        debug = true;
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    static Looper getServiceLooper() {
        return serviceLooper;
    }

    public int getConnectionStatus() {
        return xmppManager == null ? XmppManager.DISCONNECTED : xmppManager.getConnectionStatus();
    }

    static PNService getInstance() {
        return service;
    }

    public static void updateLastReadTime() {
        lastReadTime = System.currentTimeMillis();
        if(PNService.DEBUG) {
            PNLog.d(LOG_TAG, "lastReadTime = " + PNService.lastReadTime);
        }
    }

    public static void checkHeartbeat() {
        if(System.currentTimeMillis() - lastReadTime > (KEEP_ALIVE_INTERVAL + PACKET_REPLY_TIMEOUT) * 1000) {
            disconnect();
        }
    }

    public static void acquireWakeLock(int timeout) {
        if(wakeLock != null) {
            if(timeout <= 0) {
                wakeLock.acquire();
            } else {
                wakeLock.acquire(timeout * 1000);
            }
        }
//        if(wifiLock != null) {
//            wifiLock.acquire();
//        }
    }

    public static void releaseWakeLock() {
//        if(wifiLock != null && wifiLock.isHeld()) {
//            wifiLock.release();
//        }
        if(wakeLock != null && wakeLock.isHeld()) {
            wakeLock.release();
        }
    }

    static void setScreenOn(boolean screenOn) {
        PNService.screenOn = screenOn;
        if(DEBUG) {
            PNLog.d(LOG_TAG, "setScreenOn = " + screenOn);
        }
    }

    static void setPowerConnected(boolean powerConnected) {
        PNService.powerConnected = powerConnected;
        if(DEBUG) {
            PNLog.d(LOG_TAG, "setPowerConnected = " + powerConnected);
        }
    }

    static void setNetworkChanged(boolean networkChanged) {
        PNService.networkChanged = networkChanged;
        if(DEBUG) {
            PNLog.d(LOG_TAG, "networkChanged = " + networkChanged);
        }
    }
}
