<commit_before>package net.sourceforge.marathon.javafxrecorder.http;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLEncoder;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.HashMap;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;

import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;

import fi.iki.elonen.NanoHTTPD.Response;
import fi.iki.elonen.NanoHTTPD.Response.Status;
import javafx.geometry.Point2D;
import javafx.geometry.Rectangle2D;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import net.sourceforge.marathon.javafxagent.KeysMap;
import net.sourceforge.marathon.javafxrecorder.IJSONRecorder;
import net.sourceforge.marathon.javafxrecorder.JSONOMapConfig;
import net.sourceforge.marathon.javafxrecorder.JavaFxRecorderHook;
import net.sourceforge.marathon.javafxrecorder.component.RFXComponent;
import sun.net.www.protocol.http.HttpURLConnection;

public class HTTPRecorder implements IJSONRecorder {

    private int port;
    private String base;
    private String sessionID;
    private Timer clickTimer;
    private static Integer timerinterval;
    private Timer windowStateTimer;

    static {
        timerinterval = Integer.valueOf(300);
    }

    public HTTPRecorder(int port) throws IOException {
        base = "http://localhost:" + port;
        this.port = port;
        createSession();
    }

    private void createSession() throws IOException {
        sessionID = postJSON("session", createTargetDetailsObject()).getString("sessionId");
        base = "http://localhost:" + port + "/session/" + sessionID;
    }

    private JSONObject postJSON(String path, JSONObject data) throws IOException {
        Response response = post(path, data.toString());
        if (response.getStatus() != Status.OK)
            throw new RuntimeException("Internal Error: Unable to create a session.");
        return new JSONObject(new JSONTokener(response.getData()));
    }

    private JSONObject getJSON(String path) throws IOException {
        Response response = get(path);
        if (response.getStatus() != Status.OK)
            throw new RuntimeException("Internal Error: Unable to create a session.");
        return new JSONObject(new JSONTokener(response.getData()));
    }

    private JSONObject createTargetDetailsObject() {
        JSONObject o = new JSONObject();
        o.put("driver", JavaFxRecorderHook.DRIVER);
        o.put("driver.version", JavaFxRecorderHook.DRIVER_VERSION);
        o.put("platform", JavaFxRecorderHook.PLATFORM);
        o.put("platform.version", JavaFxRecorderHook.PLATFORM_VERSION);
        o.put("os", JavaFxRecorderHook.OS);
        o.put("os.version", JavaFxRecorderHook.OS_VERSION);
        o.put("os.arch", JavaFxRecorderHook.OS_ARCH);
        return o;
    }

    @Override public void recordSelect(RFXComponent r, String state) {
        recordSelect2(r, state, false);
    }

    @Override public void recordClick(RFXComponent r, MouseEvent e) {
        recordClick2(r, e, false);
    }

    @Override public void recordClick2(final RFXComponent r, MouseEvent e, boolean withCellInfo) {
        final JSONObject event = new JSONObject();
        event.put("type", "click");
        int button = e.getButton() == MouseButton.PRIMARY ? 0 : 2;
        event.put("button", button);
        event.put("clickCount", e.getClickCount());
        event.put("modifiersEx", buildModifiersText(e));
        double x = e.getX();
        double y = e.getY();
        Node source = (Node) e.getSource();
        Node target = r.getComponent();
        Point2D sts = source.localToScreen(new Point2D(0, 0));
        Point2D tts = target.localToScreen(new Point2D(0, 0));
        x = e.getX() - tts.getX() + sts.getX();
        y = e.getY() - tts.getY() + sts.getY();
        event.put("x", x);
        event.put("y", y);
        if (withCellInfo)
            event.put("cellinfo", r.getCellInfo());
        final JSONObject o = new JSONObject();
        o.put("event", event);
        fill(r, o);
        if (e.getClickCount() == 1) {
            clickTimer = new Timer();
            clickTimer.schedule(new TimerTask() {
                @Override public void run() {
                    sendRecordMessage(o);
                }
            }, timerinterval.intValue());
        } else if (e.getClickCount() == 2) {
            if (clickTimer != null) {
                clickTimer.cancel();
                clickTimer = null;
            }
            sendRecordMessage(o);
        }
    }

    @Override public void recordRawMouseEvent(final RFXComponent r, MouseEvent e) {
        final JSONObject event = new JSONObject();
        event.put("type", "click_raw");
        int button = e.getButton() == MouseButton.PRIMARY ? 0 : 2;
        event.put("button", button);
        event.put("clickCount", e.getClickCount());
        event.put("modifiersEx", buildModifiersText(e));
        Node source = (Node) e.getSource();
        Node target = r.getComponent();
        Point2D sts = source.localToScene(new Point2D(e.getX(), e.getY()));
        Point2D tts = target.sceneToLocal(sts);
        event.put("x", tts.getX());
        event.put("y", tts.getY());
        final JSONObject o = new JSONObject();
        o.put("event", event);
        fill(r, o);
        if (e.getClickCount() == 1) {
            clickTimer = new Timer();
            clickTimer.schedule(new TimerTask() {
                @Override public void run() {
                    sendRecordMessage(o);
                }
            }, timerinterval.intValue());
        } else if (e.getClickCount() == 2) {<commit_msg>fix: Fixed recording of right click<commit_after>package net.sourceforge.marathon.javafxrecorder.http;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLEncoder;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.HashMap;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;

import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;

import fi.iki.elonen.NanoHTTPD.Response;
import fi.iki.elonen.NanoHTTPD.Response.Status;
import javafx.geometry.Point2D;
import javafx.geometry.Rectangle2D;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import net.sourceforge.marathon.javafxagent.KeysMap;
import net.sourceforge.marathon.javafxrecorder.IJSONRecorder;
import net.sourceforge.marathon.javafxrecorder.JSONOMapConfig;
import net.sourceforge.marathon.javafxrecorder.JavaFxRecorderHook;
import net.sourceforge.marathon.javafxrecorder.component.RFXComponent;
import sun.net.www.protocol.http.HttpURLConnection;

public class HTTPRecorder implements IJSONRecorder {

    private int port;
    private String base;
    private String sessionID;
    private Timer clickTimer;
    private static Integer timerinterval;
    private Timer windowStateTimer;

    static {
        timerinterval = Integer.valueOf(300);
    }

    public HTTPRecorder(int port) throws IOException {
        base = "http://localhost:" + port;
        this.port = port;
        createSession();
    }

    private void createSession() throws IOException {
        sessionID = postJSON("session", createTargetDetailsObject()).getString("sessionId");
        base = "http://localhost:" + port + "/session/" + sessionID;
    }

    private JSONObject postJSON(String path, JSONObject data) throws IOException {
        Response response = post(path, data.toString());
        if (response.getStatus() != Status.OK)
            throw new RuntimeException("Internal Error: Unable to create a session.");
        return new JSONObject(new JSONTokener(response.getData()));
    }

    private JSONObject getJSON(String path) throws IOException {
        Response response = get(path);
        if (response.getStatus() != Status.OK)
            throw new RuntimeException("Internal Error: Unable to create a session.");
        return new JSONObject(new JSONTokener(response.getData()));
    }

    private JSONObject createTargetDetailsObject() {
        JSONObject o = new JSONObject();
        o.put("driver", JavaFxRecorderHook.DRIVER);
        o.put("driver.version", JavaFxRecorderHook.DRIVER_VERSION);
        o.put("platform", JavaFxRecorderHook.PLATFORM);
        o.put("platform.version", JavaFxRecorderHook.PLATFORM_VERSION);
        o.put("os", JavaFxRecorderHook.OS);
        o.put("os.version", JavaFxRecorderHook.OS_VERSION);
        o.put("os.arch", JavaFxRecorderHook.OS_ARCH);
        return o;
    }

    @Override public void recordSelect(RFXComponent r, String state) {
        recordSelect2(r, state, false);
    }

    @Override public void recordClick(RFXComponent r, MouseEvent e) {
        recordClick2(r, e, false);
    }

    @Override public void recordClick2(final RFXComponent r, MouseEvent e, boolean withCellInfo) {
        final JSONObject event = new JSONObject();
        event.put("type", "click");
        int button = e.getButton() == MouseButton.PRIMARY ? java.awt.event.MouseEvent.BUTTON1 : java.awt.event.MouseEvent.BUTTON3;
        event.put("button", button);
        event.put("clickCount", e.getClickCount());
        event.put("modifiersEx", buildModifiersText(e));
        double x = e.getX();
        double y = e.getY();
        Node source = (Node) e.getSource();
        Node target = r.getComponent();
        Point2D sts = source.localToScreen(new Point2D(0, 0));
        Point2D tts = target.localToScreen(new Point2D(0, 0));
        x = e.getX() - tts.getX() + sts.getX();
        y = e.getY() - tts.getY() + sts.getY();
        event.put("x", x);
        event.put("y", y);
        if (withCellInfo)
            event.put("cellinfo", r.getCellInfo());
        final JSONObject o = new JSONObject();
        o.put("event", event);
        fill(r, o);
        if (e.getClickCount() == 1) {
            clickTimer = new Timer();
            clickTimer.schedule(new TimerTask() {
                @Override public void run() {
                    sendRecordMessage(o);
                }
            }, timerinterval.intValue());
        } else if (e.getClickCount() == 2) {
            if (clickTimer != null) {
                clickTimer.cancel();
                clickTimer = null;
            }
            sendRecordMessage(o);
        }
    }

    @Override public void recordRawMouseEvent(final RFXComponent r, MouseEvent e) {
        final JSONObject event = new JSONObject();
        event.put("type", "click_raw");
        int button = e.getButton() == MouseButton.PRIMARY ? java.awt.event.MouseEvent.BUTTON1 : java.awt.event.MouseEvent.BUTTON3;
        event.put("button", button);
        event.put("clickCount", e.getClickCount());
        event.put("modifiersEx", buildModifiersText(e));
        Node source = (Node) e.getSource();
        Node target = r.getComponent();
        Point2D sts = source.localToScene(new Point2D(e.getX(), e.getY()));
        Point2D tts = target.sceneToLocal(sts);
        event.put("x", tts.getX());
        event.put("y", tts.getY());
        final JSONObject o = new JSONObject();
        o.put("event", event);
        fill(r, o);
        if (e.getClickCount() == 1) {
            clickTimer = new Timer();
            clickTimer.schedule(new TimerTask() {
                @Override public void run() {
                    sendRecordMessage(o);
                }
            }, timerinterval.intValue());
        } else if (e.getClickCount() == 2) {
{'fraction_non_alphanumeric': 0.12282025486250839, 'fraction_numerical': 0.004527162977867203, 'mean_word_length': 2.8332262210796917, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4447661', 'n_tokens_mistral': 3532, 'n_tokens_neox': 3462, 'n_words': 773}