package _VisualDVM.ComponentsServer.Component.PerformanceAnalyzer;
import Common.Utils.Utils_;
import Common.Visual.UI;
import _VisualDVM.ComponentsServer.Component.Component;
import _VisualDVM.ComponentsServer.Component.ComponentType;
import _VisualDVM.Global;
import _VisualDVM.Utils;
import analyzer.common.MessageJtoJ;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.Callable;
public class PerformanceAnalyzer extends Component {
    public static boolean isActive = false;
    public static Thread main_thread = null;
    ServerSocket serverSocket = null;
    Socket client = null;
    Thread process_thread = null;
    Thread server_thread = null;
    //<editor-fold desc="серверная часть">
    private int port;
    private ObjectInputStream in; // поток чтения из сокета
    private ObjectOutputStream out; // поток записи в сокет
    private MessageJtoJ message_out = null;
    private MessageJtoJ message_in = null;
    @Override
    public ComponentType getComponentType() {
        return ComponentType.PerformanceAnalyzer;
    }
    public int getPort() {
        return port;
    }
    public void setPort(int port) {
        this.port = port;
    }
    public void Update() throws Exception {
        ReplaceOldFile();
        GetVersionInfo();
    }
    @Override
    public boolean isNecessary() {
        return false;
    }
    @Override
    public String getFileName() {
        return "PerformanceAnalyzer.jar";
    }
    @Override
    public String getNewFileName() {
        return "PerformanceAnalyzer_new.jar";
    }
    public void Shutdown() {
        try {
            if (client != null) {
                client.setSoLinger(true, 500);
                client.close();
            }
            if (serverSocket != null) serverSocket.close();
        } catch (Exception ignored) {
        }
    }
    public void ReadMessageIn() throws Exception {
        message_in = (MessageJtoJ) in.readObject();
    }
    public void SendMessageOut(MessageJtoJ messageJtoJ) throws Exception {
        message_out = messageJtoJ;
        out.writeObject(message_out);
    }
    public void ConvertStatistic() throws Exception {
        message_in = (MessageJtoJ) in.readObject();
        String message = Global.mainModule.getSapfor().readStatForAnalyzer(message_in.getMessage());
        message_out = new MessageJtoJ(message, message_in.getCommand());
        out.writeObject(message_out);
    }
    public void StartServer(Callable body) throws Exception {
        serverSocket = new ServerSocket(0, 5, InetAddress.getLoopbackAddress());
        setPort(serverSocket.getLocalPort());
        server_thread = new Thread(() -> {
            try {
                client = serverSocket.accept();
                out = new ObjectOutputStream(client.getOutputStream());
                in = new ObjectInputStream(client.getInputStream());
                //------------------------------------------------------->>;
                body.call();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        });
        server_thread.start();
    }
    @Override
    public void GetVersionInfo() {
        try {
            StartServer(() -> {
                ReadMessageIn(); //на версию.
                version = (long) Double.parseDouble(message_in.getMessage());
                ReadMessageIn(); //на дату.
                date_text = message_in.getMessage();
                return null;
            });
            Utils.startScript(Global.TempDirectory, Global.ComponentsDirectory, "analyzer",
                    "java -jar -Dprism.order=sw " + Utils_.DQuotes(Global.performanceAnalyzer.getFile()) + " --port " + getPort() + " --version");
            //-
            server_thread.join();
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            Shutdown();
        }
    }
    public void ServerBody() {
        //1. нить сервера. слушать.
        try {
            StartServer(() -> {
                SendMessageOut(new MessageJtoJ(
                        Global.mainModule.HasProject() ? Global.mainModule.getProject().getAnalyzerDirectory().getAbsolutePath() : Global.PerformanceAnalyzerDirectory.getAbsolutePath(), "StatDirPath"));
                while (true) ConvertStatistic();
            });
            // UI.Info(String.valueOf(getPort()));
            process_thread = new Thread(() -> {
                try {
                    Utils.startScript(Global.TempDirectory, Global.ComponentsDirectory, "analyzer",
                            "java -jar -Dprism.order=sw " + Utils_.DQuotes(Global.performanceAnalyzer.getFile()) + " --port " + getPort());
                    //-
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            });
            process_thread.start();
            isActive = true;
            process_thread.join();
            server_thread.join();
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            Shutdown();
            isActive = false;
        }
    }
    public void Start() {
        if (isActive) {
            UI.Info("Анализатор уже запущен");
        } else {
            main_thread = new Thread(this::ServerBody);
            main_thread.start();
        }
    }
    //</editor-fold>
}
