package com.gnhz.clinic.eitc_erm_app.sightGlass;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;

public class Video {
    private static final String TAG = "czb";
    private static final int READ_MAX_LEN = 8192 * 2;
    /*一般H264帧大小不超过200k,如果解码失败可以尝试增大这个值*/
    private static int FRAME_MAX_LEN = 500 * 1024;
    private boolean DecodeModeUser = true;
    //解码后显示的surface及其宽高
    private Socket sock;
    private BufferedInputStream is;
    private OutputStream os;

    private int mTrans = 0x0F0F0F0F;
    private Handler handler;
    private DecodeUtil decodeUtil;


    public Video(Handler handler, DecodeUtil decodeUtil) {
        this.handler = handler;
        this.decodeUtil = decodeUtil;
    }

    /**
     * 连接验证
     *
     * @param os
     */
    private void sendHandleMes(OutputStream os) {
        byte[] SockBuf = new byte[12];
        SockBuf[0] = 0x5f;
        SockBuf[1] = 0x6f;
        SockBuf[10] = (byte) 11;
        SockBuf[11] = (byte) 0;
        try {
            os.write(SockBuf, 0, 12);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    int tempI;
    byte Temp;

    int MergeBuffer(byte[] NalBuf, int NalBufUsed, byte[] SockBuf, int SockBufUsed, int SockRemain) {

        for (tempI = 0; tempI < SockRemain; tempI++) {
            Temp = SockBuf[tempI + SockBufUsed];
            NalBuf[tempI + NalBufUsed] = Temp;
            mTrans <<= 8;
            mTrans |= Temp;
            if (mTrans == 1) {
                tempI++;
                break;
            }
        }
        return tempI;
    }

    private void checkSocket(Socket socket) {
        if (socket != null && !socket.isClosed()) {
            try {
                socket.close();
                Log.e(TAG, "checkSocket: closed!");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private boolean connectSocketIsOK(String ip, int port) {
        // checkSocket(sock);
        SocketAddress socketAddress = new InetSocketAddress(ip, port);
        try {
            sock = null;
            sock = new Socket();
            sock.connect(socketAddress, 2000);
            com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.h264PlayFlag = true;
            /// sock = socket;
            Log.e(TAG, "socketH264Player: connect success!");
        } catch (IOException e) {
            e.printStackTrace();
            Log.e(TAG, "socketH264Player: connect failed!");
            com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.h264PlayFlag = false;
        }
        return com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.h264PlayFlag;
    }

    public void startVideoDecode() {
        int i = 0;
        for (i = 0; i < com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.portList.size(); i++) {
            if (connectSocketIsOK("192.168.1.1", com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.portList.get(i))) {
                com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.nowPort = com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.portList.get(i);
                Log.e(TAG, "MyXUtil.nowPort " + com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.nowPort);
                break;
            }
        }
        if (!com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.h264PlayFlag) {
            String devIP = com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.getDevIP();
            if (devIP == null) {
                handler.sendEmptyMessage(3);
                return;
            }
            for (i = 0; i < com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.portList.size(); i++) {
                if (connectSocketIsOK(devIP, com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.portList.get(i))) {
                    com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.nowIP = devIP;
                    com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.nowPort = com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.portList.get(i);
                    break;
                }
            }
        }
        if (com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.h264PlayFlag) {
            Log.e(TAG, "startVideoDecode: sockt已经连接成功了！");
            int nalLen;
            int SockBufUsed;
            int bytesRead = 0;
            int NalBufUsed = 0;
            byte[] frame = new byte[FRAME_MAX_LEN];
            byte[] SockBuf = new byte[READ_MAX_LEN];
            try {
                is = new BufferedInputStream(sock.getInputStream());
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                os = sock.getOutputStream();
            } catch (IOException e) {
                e.printStackTrace();
            }
            sendHandleMes(os);
            handler.sendEmptyMessage(3);
            //循环读取数据
            while (com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.h264PlayFlag) {
                try {
                    assert is != null;
                    bytesRead = is.read(SockBuf, 0, READ_MAX_LEN);
                } catch (IOException | AssertionError e) {
                    e.printStackTrace();
                    Log.d(TAG, "run: 40003端口读取超时或者出错********************");
                    handler.sendEmptyMessage(7);
                }
                SockBufUsed = 0;
                while (bytesRead - SockBufUsed > 0) {
                    nalLen = MergeBuffer(frame, NalBufUsed, SockBuf, SockBufUsed, bytesRead - SockBufUsed);
                    NalBufUsed += nalLen;
                    SockBufUsed += nalLen;
                    //找到了就执行下面的解码，没有找到就继续循环读取数据，直到找到帧头
                    if (mTrans == 1) {
                        mTrans = 0x0F0F0F0F;
                        if (com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.h264PlayFlag && decodeUtil != null) {
                            // decodeUtil.DecodeFrame(frame, 0, NalBufUsed - 4);
                            byte[] bytes = new byte[NalBufUsed - 4];
                            System.arraycopy(frame, 0, bytes, 0, NalBufUsed - 4);
                            try {
                                DecodeUtil.arrayBlockingQueue.put(bytes);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        frame[0] = 0;
                        frame[1] = 0;
                        frame[2] = 0;
                        frame[3] = 1;
                        NalBufUsed = 4;
                    }
                }
            }

        } else {
            handler.sendEmptyMessage(3);
            Log.e(TAG, "stratVideoDecode: socket连接失败----");
        }
        Log.e(TAG, "stratVideoDecode: 结束解码，已经结束咧！*******************");
    }


    private void showCapJpg(String filename) {
        Message msg = Message.obtain();
        msg.what = 4;
        Bundle bundle = new Bundle();
        bundle.putString("filename", filename);
        msg.setData(bundle);
        handler.sendMessage(msg);
    }


    public void StartKeyScanThread() {
        try {
            com.gnhz.clinic.eitc_erm_app.sightGlass.ServerSocketUtil.serverSocket = new ServerSocket(40004);
            com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.ketThreadFlag = true;
        } catch (IOException e) {
            e.printStackTrace();
            com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.ketThreadFlag = false;
        }
        if (com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.ketThreadFlag) {
            byte[] SockBuf = new byte[22];
            int bytesRead = 0;
            Socket client = null;
            while (com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.ketThreadFlag) {
                try {
                    client = com.gnhz.clinic.eitc_erm_app.sightGlass.ServerSocketUtil.serverSocket.accept();
                } catch (IOException e) {
                    e.printStackTrace();
                    com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.ketThreadFlag = false;
                    continue;
                }
                try {
                    bytesRead = client.getInputStream().read(SockBuf, 0, SockBuf.length);
                } catch (IOException | AssertionError e) {
                    e.printStackTrace();
                }
                if ((bytesRead == 10) && (SockBuf[8] == 0)) {
                    handler.sendEmptyMessage(4);
                    Log.e(TAG, "run: button-0");
                } else if ((bytesRead == 10) && (SockBuf[8] == 1)) {
                    handler.sendEmptyMessage(4);
                    Log.e(TAG, "run: button-1");
                } else if ((bytesRead == 10) && (SockBuf[8] == 20)) {
                    handler.sendEmptyMessage(20);
                    Log.e(TAG, "StartKeyScanThread: 20");
                } else if ((bytesRead == 10) && (SockBuf[8] == 21)) {
                    handler.sendEmptyMessage(21);
                    Log.e(TAG, "StartKeyScanThread: 21");
                } else if ((bytesRead == 10) && (SockBuf[8] == 22)) {
                    handler.sendEmptyMessage(22);
                    Log.e(TAG, "StartKeyScanThread: 22");
                } else if ((bytesRead == 10) && (SockBuf[8] == 23)) {
                    handler.sendEmptyMessage(23);
                    Log.e(TAG, "StartKeyScanThread: 23");
                }
                if (!client.isClosed()) {
                    if (!client.isInputShutdown()) {
                        try {
                            client.shutdownInput();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    try {
                        client.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    client = null;
                }
            }
            Log.e(TAG, "SatrtKeyScanThread: 服务器已经结束咧------");
        }
    }

    public void closeSocket() {
        com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.h264PlayFlag = false;
        if (sock != null && !sock.isClosed()) {

            if (!sock.isInputShutdown()) {
                try {
                    sock.shutdownInput();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (!sock.isOutputShutdown()) {
                try {
                    sock.shutdownOutput();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (!sock.isClosed()) {
                try {
                    sock.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            sock = null;
            Log.e(TAG, "closeSocket: socket已经关闭咧！");
        }
    }

    public void showsdjpg(String filename, boolean newfile) {
        Message msg = new Message();
        msg.what = 6;
        Bundle bundle = new Bundle();
        bundle.putString("filename", filename);
        bundle.putBoolean("newfile", newfile);
        msg.setData(bundle);
        handler.sendMessage(msg);
    }
}
