package com.qy.agv.receiver;

import static com.qy.agv.util.Constant.DATETIME_CONTINUOUS_FORMATE;
import static com.qy.agv.util.Constant.TIME_FORMATE;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;

import com.qy.agv.util.Constant;
import com.qy.agv.util.DateUtil;
import com.qy.agv.util.StringUtils;

import org.apache.log4j.Logger;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.InetSocketAddress;
import java.net.NoRouteToHostException;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;


/**
 * <p>
 * socket连接服务
 */
public class SocketService extends Service {

    /*socket*/
    private Socket socket;
    /*连接线程*/
    private Thread connectThread;
    private Timer timer = new Timer();
    private OutputStream outputStream;

    private final SocketBinder sockerBinder = new SocketBinder();
    private TimerTask task;

    /*默认重连*/
    private boolean isReConnect = true;
    private final Handler handler = new Handler(Looper.getMainLooper());
    public static Logger mylog =Logger.getLogger(SocketService.class);
    private final Intent intent = new Intent(Constant.RECEIVER_MSG);
    private Long lastTime = 0L;
    private int bleSeq = 0;
    public volatile Map<String, Map<String, String>> checkID = new HashMap<>();
    public static String status = "";


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

    public class SocketBinder extends Binder {
        /*返回SocketService 在需要的地方可以通过ServiceConnection获取到SocketService  */
        public SocketService getService() {
            return SocketService.this;
        }
    }

    @Override
    public void onCreate() {
        /*初始化socket*/
        try {
            if(Constant.robotModel != null
                    && !StringUtils.isEmpty(Constant.robotModel.getRobotIp())) {
                initSocket();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }

    /*初始化socket*/
    private void initSocket() {
        if (socket == null && connectThread == null) {
            connectThread = new Thread(new Runnable() {
                @Override
                public void run() {

                    socket = new Socket();
                    try {
                        /*超时时间为2秒*/
                        socket.connect(new InetSocketAddress(Constant.robotModel.getRobotIp(), Constant.robotModel.getPort()), 15000);
                        /*连接成功的话  发送心跳包*/
                        if (socket.isConnected()) {
                            /*因为Toast是要运行在主线程的  这里是子线程  所以需要到主线程哪里去显示toast*/
                            toastMsg("连接成功");

                            lastTime = System.currentTimeMillis();
                            sendBeatData();
                            new Thread(new Runnable() {
                                @Override
                                public void run() {
                                    rec();
                                }
                            }).start();
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                        if (e instanceof SocketTimeoutException) {
                            mylog.error("连接超时，正在重连");
                            toastMsg("连接超时");
                            try {
                                Thread.sleep(1000);
                            } catch (InterruptedException ex) {
                                return;
                            }
                            releaseSocket();

                        } else if (e instanceof NoRouteToHostException) {
                            mylog.error("地址不存在，请检查");
                            toastMsg("地址不存在");
                            stopSelf();

                        } else if (e instanceof ConnectException) {
                            mylog.error("连接异常或被拒绝，请检查");
                            toastMsg("连接异常或被拒绝");
                            try {
                                Thread.sleep(5000);
                            } catch (InterruptedException ex) {
                                return;
                            }
                            releaseSocket();
                        }
                    }
                }
            });
            /*启动连接线程*/
            connectThread.start();
        }
    }


    private void showCommand(String rec){
        if(!rec.contains(",")){
            mylog.error("无效指令");
            toastMsg("无效指令");
            return;
        }
        String recID = rec.split(",")[1];
        if(checkID.containsKey(recID)){
            Map<String, String> str = checkID.get(rec);
            if(str == null){
                return;
            }
            toastMsg(str.get(rec));
            checkID.remove(rec);
        }else {
            intent.putExtra("json", rec);
            sendBroadcast(intent);
        }
    }

    /*因为Toast是要运行在主线程的   所以需要到主线程哪里去显示toast*/
    private void toastMsg(final String msg) {
        status = msg;
//        handler.post(new Runnable() {
//            @Override
//            public void run() {
//                Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
//            }
//        });
    }

    /*发送数据*/
    public boolean sendData(final String json) {
        if (socket != null && socket.isConnected()) {
            /*发送指令*/
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        tcpClient(json);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();
            return true;
        } else {
            toastMsg("机器人未连接,请重试");
        }
        return false;
    }

    /*定时发送数据*/
    private void sendBeatData() {
        if (timer == null) {
            timer = new Timer();
        }

        if (task == null) {
            task = new TimerTask() {
                @Override
                public void run() {
                    try {
                        outputStream = socket.getOutputStream();
                        /*这里的编码方式根据你的需求去改*/
                        long longTime = System.currentTimeMillis() - lastTime;
                        if(longTime > 70000){
                            releaseSocket();
                        }
                        String msg = "HpingT";
                        outputStream.write((msg+"\n").getBytes(StandardCharsets.UTF_8));
                        outputStream.flush();
                    } catch (Exception e) {
                        /*发送失败说明socket断开了或者出现了其他错误*/
                        toastMsg("连接断开，正在重连");
                        /*重连*/
                        releaseSocket();
                        e.printStackTrace();
                    }
                }
            };
        }
        timer.schedule(task, 0, 10000);
    }

    private void rec(){
        try{
            while (true) {
                if(socket!=null && !socket.isInputShutdown()) {
                    try {
                        BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                        String inMsg = in.readLine();//服务器返回的数据
                        if (StringUtils.isEmpty(inMsg)) {
                            socket = null;
                            return;
                        }
                        inMsg = inMsg + System.getProperty("line.separator");
                        inMsg = inMsg.replace("\n", "");
                        lastTime = System.currentTimeMillis();
                        mylog.info("received: " + inMsg);
                        if (!StringUtils.isEmpty(inMsg)) {
                            showCommand(inMsg);
                        }
                    }catch (SocketException ex){
                        TimeUnit.SECONDS.sleep(5);
                    }catch (Exception ex){
                        mylog.error(ex);
                        ex.printStackTrace();
                        TimeUnit.SECONDS.sleep(5);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void tcpClient(String json){
        try{
            if(socket == null){
                throw new SocketException("重新连接");
            }
            outputStream = socket.getOutputStream();
            outputStream.write((json+"\n").getBytes(StandardCharsets.UTF_8));
            outputStream.flush();
            mylog.info("发送：" + json);
            if(!isReConnect){
                releaseSocket();
            }
        }catch (SocketException ex){
            toastMsg("发送异常，重新连接");
            releaseSocket();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /*释放资源*/
    private void releaseSocket() {

        if (task != null) {
            task.cancel();
            task = null;
        }
        if (timer != null) {
            timer.purge();
            timer.cancel();
            timer = null;
        }

        if (outputStream != null) {
            try {
                outputStream.close();

            } catch (IOException e) {
                e.printStackTrace();
            }
            outputStream = null;
        }

        if (socket != null) {
            try {
                socket.close();
            } catch (IOException e) {
            }
            socket = null;
        }

        if (connectThread != null) {
            connectThread = null;
        }

        /*重新初始化socket*/
        if (isReConnect) {
            try {
                TimeUnit.SECONDS.sleep(5);
                initSocket();
            }catch (Exception e){
                e.printStackTrace();
            }
        }

    }

    public String getSendID() {
        bleSeq++;
        if (bleSeq > 9) {
            bleSeq = 0;
        }
        return DateUtil.getCurrDate(DATETIME_CONTINUOUS_FORMATE) + "" + bleSeq;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.i("SocketService", "onDestroy");
        isReConnect = false;
        sendData("Hclose,T");
    }
}


