package com.efounder.chat.service;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.os.Binder;
import android.os.IBinder;
import android.text.TextUtils;
import android.util.Log;

import com.efounder.aspect.annotation.ExecutionTime;
import com.efounder.chat.event.PushTokenEvent;
import com.efounder.chat.http.GetHttpUtil;
import com.efounder.chat.http.JFCommonRequestManager;
import com.efounder.chat.http.WeChatHttpLoginManager;
import com.efounder.chat.utils.CommonThreadPoolUtils;
import com.efounder.chat.utils.ServiceUtils;
import com.efounder.constant.EnvironmentVariable;
import com.efounder.frame.utils.NetStateBroadcastReceiver;
import com.efounder.message.manager.JFMessageManager;
import com.efounder.message.socket.JFSocketManager;
import com.efounder.util.AppContext;
import com.efounder.util.BaseDeviceUtils;
import com.efounder.util.MobilePushUtils;
import com.efounder.util.StringUtil;
import com.utilcode.util.AppUtils;
import com.utilcode.util.LogUtils;
import com.utilcode.util.Utils;

import org.apache.commons.lang3.time.StopWatch;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;

import static com.efounder.frame.utils.Constants.CHAT_PASSWORD;
import static com.efounder.frame.utils.Constants.CHAT_USER_ID;
import static com.efounder.frame.utils.NetStateBroadcastReceiver.isNetActive;

/****
 * 消息服务：做两件事
 * 1.启动一个线程，不断监视TCP消息通道连接状态，一旦断线，尝试重连
 * 2.接收网络状态变化的广播，断线重连
 */
public class MessageService extends Service implements WeChatHttpLoginManager.LoginListener {
    public static final String EXTRA_KEY_IS_LOGIN_IMMEDIATELY = "LOGIN_IMMEDIATELY";

    private static final String TAG = "MessageService";
    /**
     * 登录超时时间
     */
    private static final int LOGIN_TIME_OUT = 15 * 1000;
    private Binder binder;
    /**
     * 登陆开始时间
     */
    private long loginBeginTime;
    /**
     * 是否正在登录标记
     **/
    private volatile boolean isLogining;
    /**
     * 控制监视通道连接状态线程是否运行
     **/
    private boolean isWatchChannelActiveThreadRunning = true;
    /**
     * 监视TCP消息通道连接状态线程
     */
    private WatchChannelActiveThread watchChannelActiveThread;

    /**
     * 登录消息服务，并激活消息通道 成功失败的监听
     */
    private static List<MessageServiceLoginListener> loginListenerList = new ArrayList<>();
    /**
     * 网络变化的监听
     */
    private static List<MessageServiceNetStateListener> netStateListeners = new ArrayList<>();

    /**
     * 网络状态广播接收器
     **/
    private NetStateBroadcastReceiver mReceiver = new NetStateBroadcastReceiver();

    //应用是否在前台
    private boolean isOnForeground = true;

    private NetStateBroadcastReceiver.NetStateListener netStateListener = new NetStateBroadcastReceiver.NetStateListener() {
        @Override
        public void onConnected(int netState) {
            //尝试登录
            tryLogin();
        }

        @Override
        public void onDisconnected(int netState) {
            //监听网络状态的观察者派发
            for (MessageServiceNetStateListener messageServiceNetStateListener : netStateListeners) {
                messageServiceNetStateListener.netStateChange(0);
            }
        }
    };

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i(TAG, TAG + "---------onCreate");

        // 创建 Binder
        binder = new MessageServiceBinder();
        //注册网络变化广播
        IntentFilter mFilter = new IntentFilter();
        mFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
        mReceiver.setNetStateListener(netStateListener);
        registerReceiver(mReceiver, mFilter);
        //注册eventbus
        EventBus.getDefault().register(this);
        //启动监视线程，断线重连
        watchChannelActiveThread = new WatchChannelActiveThread();
        watchChannelActiveThread.setDaemon(true);//设为守护线程
        isLogining = false;
        //应用前后台监听
        AppUtils.registerAppStatusChangedListener(this, new Utils.OnAppStatusChangedListener() {
            @Override
            public void onForeground() {
                isOnForeground = true;
            }

            @Override
            public void onBackground() {
                if (!MobilePushUtils.isSupportPush()) {
                    //如果不支持推送，在后台的时候无需进行操作
                    return;
                }
                isOnForeground = false;
                HashMap<String, String> paramMap = new HashMap<>();
                String userId = EnvironmentVariable.getProperty(CHAT_USER_ID);
                String password = EnvironmentVariable.getProperty(CHAT_PASSWORD);
                paramMap.put("userId", userId);
                paramMap.put("passWord", password);
                paramMap.put("deviceId", getDeviceId(getApplicationContext()));
                paramMap.put("subAppId", EnvironmentVariable.getProperty("subAppId", ""));
                // app退到后台时，调用臧老师接口
                JFCommonRequestManager.getInstance(getApplicationContext()).requestGetByAsyn(
                        TAG, GetHttpUtil.ROOTURL + "/IMServer/user/offline", paramMap, null);
                //应用在后台，断开socket 连接
                stopSocket();
            }
        });
    }

    /**
     * 关闭socket链接
     * 需要放到线程中，经过测试，消息服务连接上时，关闭socket需要2.3s，没连接的时候0s
     * 所以需要放到线程中
     */
    private void stopSocket() {

        CommonThreadPoolUtils.execute(new Runnable() {
            @Override
            public void run() {
                StopWatch stopWatch = new StopWatch();
                stopWatch.start();
                try {
                    JFSocketManager.getInstance().stop();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                stopWatch.stop();
//                Log.e(TAG, "关闭JFSocketManager需要时间：" + stopWatch.getTime());
            }
        });
    }


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(TAG, TAG + "---------onStartCommand");
        //START_STICKY 模式下 service被回收并重启，intent = null
        if (intent != null && intent.hasExtra(EXTRA_KEY_IS_LOGIN_IMMEDIATELY) && intent.getBooleanExtra(EXTRA_KEY_IS_LOGIN_IMMEDIATELY, false)) {
            loginImmediately();
            startLoginInThread();
        } else {
            startLoginInThread();
        }
        return START_STICKY;
    }

    private void startLoginInThread() {
        //检测线程是否存活（防止service存在，线程死掉）
        isWatchChannelActiveThreadRunning = true;
        if (!watchChannelActiveThread.isAlive()) {
            watchChannelActiveThread.start();
        }
    }

    private long loginImmediatelyTime;

    /***
     * 立即登陆
     */
    private void loginImmediately() {
        if (System.currentTimeMillis() - loginImmediatelyTime > LOGIN_TIME_OUT) {
            loginImmediatelyTime = System.currentTimeMillis();//记录时间
            isLogining = false;
            tryLogin();
        }
    }

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

    @Override
    public boolean onUnbind(Intent intent) {
        return super.onUnbind(intent);
    }


    /**
     * 使用黏性事件是为了发送事件之后再订阅该事件也能收到该事件
     *
     * @param event
     */
    @Subscribe(threadMode = ThreadMode.MAIN, priority = 1, sticky = true)
    public void onGetToken(PushTokenEvent event) {
        String token = event.getHuaWeiPushToken();
        //存储新的pushtoken
        EnvironmentVariable.setProperty("pushToken", token);
        EventBus.getDefault().removeStickyEvent(event);
        //断开消息服务（等待检测消息服务断开后会自动重连）
        stopSocket();
        LogUtils.i("pushToken:" + token);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.i(TAG, TAG + "---------onDestroy");
        //注销广播
        if (mReceiver != null) {
            unregisterReceiver(mReceiver);
        }
        //停掉监视线程
        isWatchChannelActiveThreadRunning = false;
        isLogining = false;
        //停掉消息通道
//        JFSocketManager.getInstance().stop();
        stopSocket();
        //移除登陆监听
        WeChatHttpLoginManager.getInstance(getApplicationContext()).removeLoginListener(this);
        AppUtils.unregisterAppStatusChangedListener(this);
        EventBus.getDefault().unregister(this);
    }


    /**
     * binder
     *
     * @author hu
     */
    public class MessageServiceBinder extends Binder {
        /**
         * 获取MessageService
         *
         * @return service
         */
        public MessageService getService() {
            return MessageService.this;
        }
    }


    /**
     * 尝试登录
     */
    private synchronized void tryLogin() {
        String userId = EnvironmentVariable.getProperty(CHAT_USER_ID);
        String password = EnvironmentVariable.getProperty(CHAT_PASSWORD);
        if (TextUtils.isEmpty(userId) || TextUtils.isEmpty(password)) {
            return;
        }
        //如果30秒后，还在登陆，将isLogining=false(相当于30秒超时)
        if (System.currentTimeMillis() - loginBeginTime > LOGIN_TIME_OUT && isLogining) {
            isLogining = false;
            Log.i(TAG, "------连接超过30秒，手动标记 isLogining=false");
        }
        //只要有网，并且没连上，并且应用在前台才连接 就一直连
        if (isNetActive() && !JFMessageManager.isChannelActived() && !isLogining && isOnForeground) {
            // 消息服务登录
            Log.i(TAG, "断线重连------1.断线重连 begin");
            markIsLogining();
            //监听网络状态的观察者派发-连接断开
            for (MessageServiceNetStateListener messageServiceNetStateListener : netStateListeners) {
                messageServiceNetStateListener.netStateChange(0);
            }
            WeChatHttpLoginManager weChatHttpRequest = WeChatHttpLoginManager.getInstance(getApplicationContext());
            weChatHttpRequest.addLoginListener(this);
            weChatHttpRequest.httpLogin(userId, password);
        }
    }

    /**
     * 标记正在登陆
     */
    private void markIsLogining() {
        isLogining = true;
        loginBeginTime = System.currentTimeMillis();
    }

    @Override
    public void onLoginSuccess() {
        isLogining = false;
        Log.i(TAG, "断线重连-----2.消息服务连接成功");
        for (MessageServiceLoginListener loginListener : loginListenerList) {
            loginListener.onLoginSuccess();
        }
        //TODO TCP连接恢复
        //监听网络状态的观察者派发
        for (MessageServiceNetStateListener messageServiceNetStateListener : netStateListeners) {
            messageServiceNetStateListener.netStateChange(1);
        }


        if (!ServiceUtils.isServiceRunning(getApplicationContext(), SystemInfoService.class.getCanonicalName()) && !StringUtil.isEmpty(EnvironmentVariable.getProperty(CHAT_USER_ID))) {
            Log.i(TAG, "---SystemInfoService---2");
            String userID = EnvironmentVariable.getUserID();
            if (userID != null && !"".equals(userID)) {
                startService(new Intent(getApplicationContext(), SystemInfoService.class));
            }
        }
    }

    @Override
    public void onLoginFail(String errorMsg) {
        isLogining = false;
        //停掉tcp连接
//		JFSocketManager.getInstance().stop();
        //移除监听
        Log.e(TAG, "断线重连-----2.登录失败 :" + errorMsg);
        for (MessageServiceLoginListener loginListener : loginListenerList) {
            loginListener.onLoginFail(errorMsg);
        }
    }

    /**
     * 监视通道连接状态线程
     */
    private class WatchChannelActiveThread extends Thread {
        @Override
        public void run() {
            super.run();
            //获取用id 和 密码
            while (isWatchChannelActiveThreadRunning) {

                try {
                    Log.d(TAG, "----------监视消息服务连接状态线程 运行中。。。isWatchChannelActiveThreadRunning：" + isWatchChannelActiveThreadRunning);
                    tryLogin();
                    Thread.sleep(1000 * 5);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }


    public interface MessageServiceLoginListener {

        void onLoginSuccess();

        void onLoginFail(String errorMsg);

    }

    public static void addMessageServiceLoginListener(MessageServiceLoginListener loginListener) {
        if (!loginListenerList.contains(loginListener)) {
            loginListenerList.add(loginListener);
        }
    }

    public static void removeMessageServiceLoginListener(MessageServiceLoginListener loginListener) {
        if (loginListenerList.contains(loginListener)) {
            loginListenerList.remove(loginListener);
        }
    }


    public interface MessageServiceNetStateListener {

        //返回网络状态的类型  0：无网络，tcp掉线  1：登录成功
        public void netStateChange(int net_state);

    }

    //网络状态观察者模式 添加观察者  edit by lc
    public static void addMessageServiceNetStateListener(MessageServiceNetStateListener netStateListener) {
        if (!netStateListeners.contains(netStateListener)) {
            netStateListeners.add(netStateListener);
        }
    }

    //网络状态观察者模式 移除观察者
    public static void removeMessageServiceNetStateListener(MessageServiceNetStateListener netStateListener) {
        if (netStateListeners.contains(netStateListener)) {
            netStateListeners.remove(netStateListener);
        }
    }

    /**
     * 获取设备deviceid
     *
     * @param context
     * @return
     */
    public static String getDeviceId(Context context) {
        return BaseDeviceUtils.getUniqueId(AppContext.getInstance());
    }
}

