package com.yutou.jianr_mg.Tools;

import android.content.Context;
import android.net.wifi.WifiManager;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;

import com.kaopiz.kprogresshud.KProgressHUD;
import com.yutou.jianr_mg.Application;
import com.yutou.jianr_mg.Data.AppData;
import com.yutou.jianr_mg.Interfaces.HttpInterface;
import com.yutou.jianr_mg.Interfaces.ModInterface;

import org.json.JSONObject;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;

import me.drakeet.materialdialog.MaterialDialog;

import static android.content.Context.WIFI_SERVICE;

/**
 * Socket客户端，接受模式为服务端，传输模式为客户端
 */
public class SocketTools {
    private Context context;
    private boolean model;
    private Socket socket;
    private ServerSocket serverSocket;
    private HttpInterface httpInterface;
    private List<Socket> sockets;
    private static int CODE_SUCCESS = 200;
    private static int CODE_ERROR = 500;
    private KProgressHUD hud;

    /**
     * 初始化客户端
     *
     * @param model true为接受模式，false为传输模式
     */
    public SocketTools(Context context, boolean model, HttpInterface httpInterface) {
        this.context = context;
        this.model = model;
        this.httpInterface = httpInterface;
        this.sockets = new ArrayList<>();
        hud = Utils.showLoading(context, null, "扫描中");

        init();
    }

    private void init() {
        new Thread(() -> {
            if (model) {
                try {
                    httpInterface.httpGetData("等待链接", CODE_SUCCESS);
                    startService();
                    httpInterface.httpGetData("链接成功！", CODE_SUCCESS);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else {
                AppData.handler.post(() -> hud.show());
                scanAddress((flag, type) -> {
                    AppData.handler.post(()->hud.setLabel("扫描中..."+type));
                    if(type==0){
                         AppData.handler.post(() -> hud.dismiss());
                        showManualDialog();
                        return;
                    }
                    if (sockets.isEmpty()) {
                        return;
                    }
                    if(!flag){

                        return;
                    }
                    List<String> list = new ArrayList<>();
                    for (Socket socket : sockets) {
                        list.add(socket.getInetAddress().getHostAddress());
                    }
                    AppData.handler.post(() -> {
                        hud.dismiss();
                        showDialog(list);
                    });
                });

            }
        }).start();
    }

    private void showManualDialog() {
        AppData.handler.post(()->{
            MaterialDialog dialog=new MaterialDialog(context);
            TextView textView=new TextView(context);
            EditText editText=new EditText(context);
            LinearLayout linearLayout=new LinearLayout(context);
            textView.setText("请输入IP");
            linearLayout.setOrientation(LinearLayout.VERTICAL);
            linearLayout.addView(textView);
            linearLayout.addView(editText);
            dialog.setTitle("没有扫描到？");
            dialog.setContentView(linearLayout);
            dialog.setPositiveButton("链接",v -> {
               dialog.dismiss();
               new Thread(() -> {
                   try {
                       System.out.println("地址:"+editText.getText().toString()+" 端口:2336");
                       Socket socket=new Socket(editText.getText().toString().trim(),2336);
                       linkService(socket);

                   } catch (IOException e) {
                       e.printStackTrace();
                   }
               }).start();
            });
            dialog.setNegativeButton("取消",v -> {
                dialog.dismiss();
            });
            dialog.show();
        });
    }

    private void showDialog(List<String> text) {
        MaterialDialog dialog = new MaterialDialog(context);
        ListView listView = new ListView(context);
        listView.setAdapter(new ArrayAdapter<>(context, android.R.layout.simple_list_item_1, text));
        listView.setOnItemClickListener((parent, view, position, id) -> {
            Socket socket = sockets.get(position);
            KProgressHUD dhud=Utils.showLoading(context,null,"传输中");
            dhud.show();
            new Thread(() -> {
                System.out.println("开始传输:");
                linkService(socket);
                System.out.println("传输完毕");
                AppData.handler.post(()->{dhud.dismiss();dialog.dismiss();});
                dhud.dismiss();
            }).start();

        });

        dialog.setTitle("扫描到主机");
        dialog.setContentView(listView);
        dialog.setPositiveButton("关闭", v -> {
            dialog.dismiss();
        });
        dialog.setCanceledOnTouchOutside(true);
        dialog.show();
    }

    private void linkService(Socket socket) {
        OutputStream outputStream;
        try {
            outputStream = socket.getOutputStream();
            outputStream.write("ok".getBytes());
            outputStream.flush();
            String[] data = Utils.Base64Encode(new File("/data/data/" + context.getPackageName() + "/databases/game_data_db"));
            if (data == null)
                return;
            JSONObject json = new JSONObject();
            json.put("state", 1);
            json.put("size", new File("/data/data/" + context.getPackageName() + "/databases/game_data_db").length());
            json.put("path","/data/data/" + context.getPackageName() + "/databases/");
            json.put("fileName","game_data_db");
            json.put("length",data.length);
            for (int i = 0; i < data.length; i++) {
                json.put("index",i);
                json.put("data",data[i]);
                outputStream.write((json.toString()+"\n").getBytes());
                outputStream.flush();
            }
           // json.put("data", data);
           // outputStream.write(json.toString().getBytes());
          //  outputStream.flush();
            outputStream.close();
            socket.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private boolean flag = true;
    private List<Socket> socketList;

    private void startService() {
        socketList = new ArrayList<>();

        AppData.handler.post(()->{ hud=Utils.showLoading(context,"本地IP:"+getLocalAddress(),"等待中");hud.show();});
        while (flag) {
            try {
                ServerSocket serverSocket = new ServerSocket(2336);
                Socket socket = serverSocket.accept();
                if (!flag) {
                    serverSocket.close();
                    return;
                }
                serverSocket.close();
                socketList.add(socket);
                testSocket(socket);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    private void testSocket(Socket socket) {
        try {
            InputStream inputStream = socket.getInputStream();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] bytes = new byte[1024];
            int len = 0;
            while ((len = inputStream.read(bytes)) != -1) {
                baos.write(bytes, 0, len);
                if (len == 2) {
                    break;
                }
            }
            baos.flush();
            String tmp = baos.toString();
            baos.close();
            System.out.println(tmp);
            if (tmp.equals("ok")) {
                flag = false;
                AppData.handler.post(()->hud.dismiss());
                for (Socket s : socketList) {
                    if (!s.equals(socket)) {
                        s.close();
                    }
                }

                start(socket, inputStream);
            }
        } catch (Exception e) {
            // TODO: handle exception
        }
    }

    private void start(Socket socket, InputStream input) {

        AppData.handler.post(()->{  hud=Utils.showLoading(context,null,"接收中");hud.show();});
        httpInterface.httpGetData("确认为:" + socket.getInetAddress().getHostAddress(), CODE_SUCCESS);
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] bytes = new byte[2048];
            int len = 0;
            while ((len = input.read(bytes)) > -1) {
                baos.write(bytes, 0, len);
                baos.flush();
            }
            JSONObject json = new JSONObject(baos.toString());
            File file = new File(json.getString("path")+json.getString("fileName"));
            if (file.exists()) {
                file.delete();
            }
            String [] list=baos.toString().split("\n");
            StringBuffer sb = new StringBuffer();
            for (String d : list) {
                if(d.trim().length()==0) {
                    continue;
                }
                try {
                    JSONObject tmp = new JSONObject(d);
                   sb.append(tmp.getString("data")+"\n");
                } catch (Exception e) {
                    // TODO: handle exception
                }
            }
            System.out.println("保存路径："+file.getAbsolutePath());
            Utils.Base64Decode(sb.toString(), file);
            AppData.handler.post(()->{hud.dismiss();Utils.toast(context,"重启盒子生效");});
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }


    private void scanAddress(ModInterface modInterface) {
        String mAddress = getLocalAddress();
        if (mAddress == null) {
            httpInterface.httpGetData("非局域网环境，请检查WIFI状态", CODE_ERROR);
            return;
        }
        String ipGroup = mAddress.split("\\.")[0] + "." + mAddress.split("\\.")[1] + "." + mAddress.split("\\.")[2];
        List<Thread> list = new ArrayList<>();
        for (int i = 1; i < 255; i++) {
            int finalI = i;

            Thread thread = new Thread(() -> {
                String address = ipGroup + "." + finalI;
                if (!address.equals(mAddress)) {
                    try {
                        Socket tSocket = new Socket();
                        tSocket.connect(new InetSocketAddress(address, 2336),1000);
                        sockets.add(tSocket);
                    } catch (IOException ignored) {
                    }

                }

            });
            list.add(thread);
            thread.start();

        }
        scan(list, modInterface);
    }

    private void scan(List<Thread> list, ModInterface modInterface) {
        if (list.isEmpty()) {
            modInterface.onAction(true, -1);
            return;
        }
        Iterator<Thread> iterator = list.iterator();
        while (iterator.hasNext()) {
            Thread thread = iterator.next();

            if (!thread.isAlive()) {
                iterator.remove();
            }
        }
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        modInterface.onAction(false,list.size());
        scan(list, modInterface);
    }

    private String getLocalAddress() {
        String address = null;
        try {
            WifiManager wm = (WifiManager) Application.application.getSystemService(WIFI_SERVICE);
            int ipAddressInt = wm.getConnectionInfo().getIpAddress();
            address = String.format(Locale.getDefault(), "%d.%d.%d.%d", (ipAddressInt & 0xff), (ipAddressInt >> 8 & 0xff), (ipAddressInt >> 16 & 0xff), (ipAddressInt >> 24 & 0xff));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return address;
    }
}
