// Path: src/main/java/com/redcanari/js/wrappers/TextEditorWrapper.java
// public class TextEditorWrapper implements ITextEditor {
// 
//     final ITextEditor textEditor;
//     byte[] text = null;
// 
//     public TextEditorWrapper(ITextEditor textEditor) {
//         this.textEditor = textEditor;
//         textEditor.getComponent().addHierarchyListener(e -> {
//             text = textEditor.getText();
//         });
//     }
// 
//     @Override
//     public Component getComponent() {
//         return textEditor.getComponent();
//     }
// 
//     @Override
//     public void setEditable(boolean b) {
//         if (Platform.isFxApplicationThread())
//             SwingUtilities.invokeLater(() -> textEditor.setEditable(b));
//         else
//             textEditor.setEditable(b);
//     }
// 
//     @Override
//     public void setText(byte[] bytes) {
//         text = bytes;
//         if (Platform.isFxApplicationThread())
//             SwingUtilities.invokeLater(() -> textEditor.setText(bytes));
//         else
//             textEditor.setText(bytes);
//     }
// 
//     @Override
//     public byte[] getText() {
//         if (Platform.isFxApplicationThread())
//             return text;
//         return textEditor.getText();
//     }
// 
//     @Override
//     public boolean isTextModified() {
//         return textEditor.isTextModified();
//     }
// 
//     @Override
//     public byte[] getSelectedText() {
//         return textEditor.getSelectedText();
//     }
// 
//     @Override
//     public int[] getSelectionBounds() {
//         return textEditor.getSelectionBounds();
//     }
// 
//     @Override
//     public void setSearchExpression(String s) {
//         if (Platform.isFxApplicationThread())
//             SwingUtilities.invokeLater(() -> textEditor.setSearchExpression(s));
//         else
//             textEditor.setSearchExpression(s);
//     }
// }
// 
// Path: src/main/java/com/redcanari/swing/SwingFXUtilities.java
// public class SwingFXUtilities {
// 
//     public static <T> void invokeLater(Callable<T> callable, JSObject callback) {
//         SwingUtilities.invokeLater(() -> {
//             try {
//                 final T result = callable.call();
//                 if (callback != null) {
//                     Platform.runLater(() -> callback.call("call", null, result));
//                 }
//             } catch (Exception e) {
//                 e.printStackTrace();
//             }
//         });
//     }
// 
//     public static <T> T invokeAndWait(Callable<T> callable) throws TimeoutException, ExecutionException, InterruptedException {
//         //blocks until future returns
//         FutureTask<T> task = new FutureTask<>(callable);
//         SwingUtilities.invokeLater(task);
//         return task.get();
//     }
// 
// 
// 
// }


import burp.*;
import com.redcanari.js.proxies.*;
import com.redcanari.js.wrappers.TextEditorWrapper;
import com.redcanari.swing.SwingFXUtilities;
import javafx.scene.web.WebEngine;
import netscape.javascript.JSObject;
import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.net.CookieHandler;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
     * the extension and of Burp Suite. Saved settings can be retrieved using the method
     * {@link #loadExtensionSetting(String)}.
     *
     * @param name  The name of the setting.
     * @param value The value of the setting. If this value is {@code null} then any existing setting with the specified
     *              name will be removed.
     */
    public void saveExtensionSetting(String name, String value) {
        SwingUtilities.invokeLater(() -> burpExtenderCallbacks.saveExtensionSetting(name, value));
    }


    /**
     * This method is used to load configuration settings for the extension that were saved using the method
     * {@link #saveExtensionSetting(String, String)}.
     *
     * @param name The name of the setting.
     * @return The value of the setting, or {@code null} if no value is set.
     */
    public String loadExtensionSetting(String name) throws InterruptedException, ExecutionException, TimeoutException {
        return SwingFXUtilities.invokeAndWait(() -> burpExtenderCallbacks.loadExtensionSetting(name));
    }


    /**
     * This method is used to create a new instance of Burp's plain text editor, for the extension to use in its own UI.
     *
     * @return an instance of {@link burp.ITextEditor}
     */
    public ITextEditor createTextEditor() {
// Path: src/main/java/com/redcanari/js/wrappers/TextEditorWrapper.java
// public class TextEditorWrapper implements ITextEditor {
// 
//     final ITextEditor textEditor;
//     byte[] text = null;
// 
//     public TextEditorWrapper(ITextEditor textEditor) {
//         this.textEditor = textEditor;
//         textEditor.getComponent().addHierarchyListener(e -> {
//             text = textEditor.getText();
//         });
//     }
// 
//     @Override
//     public Component getComponent() {
//         return textEditor.getComponent();
//     }
// 
//     @Override
//     public void setEditable(boolean b) {
//         if (Platform.isFxApplicationThread())
//             SwingUtilities.invokeLater(() -> textEditor.setEditable(b));
//         else
//             textEditor.setEditable(b);
//     }
// 
//     @Override
//     public void setText(byte[] bytes) {
//         text = bytes;
//         if (Platform.isFxApplicationThread())
//             SwingUtilities.invokeLater(() -> textEditor.setText(bytes));
//         else
//             textEditor.setText(bytes);
//     }
// 
//     @Override
//     public byte[] getText() {
//         if (Platform.isFxApplicationThread())
//             return text;
//         return textEditor.getText();
//     }
// 
//     @Override
//     public boolean isTextModified() {
//         return textEditor.isTextModified();
//     }
// 
//     @Override
//     public byte[] getSelectedText() {
//         return textEditor.getSelectedText();
//     }
// 
//     @Override
//     public int[] getSelectionBounds() {
//         return textEditor.getSelectionBounds();
//     }
// 
//     @Override
//     public void setSearchExpression(String s) {
//         if (Platform.isFxApplicationThread())
//             SwingUtilities.invokeLater(() -> textEditor.setSearchExpression(s));
//         else
//             textEditor.setSearchExpression(s);
//     }
// }
// 
// Path: src/main/java/com/redcanari/swing/SwingFXUtilities.java
// public class SwingFXUtilities {
// 
//     public static <T> void invokeLater(Callable<T> callable, JSObject callback) {
//         SwingUtilities.invokeLater(() -> {
//             try {
//                 final T result = callable.call();
//                 if (callback != null) {
//                     Platform.runLater(() -> callback.call("call", null, result));
//                 }
//             } catch (Exception e) {
//                 e.printStackTrace();
//             }
//         });
//     }
// 
//     public static <T> T invokeAndWait(Callable<T> callable) throws TimeoutException, ExecutionException, InterruptedException {
//         //blocks until future returns
//         FutureTask<T> task = new FutureTask<>(callable);
//         SwingUtilities.invokeLater(task);
//         return task.get();
//     }
// 
// 
// 
// }


// Path: src/main/java/com/redcanari/js/BurpExtenderCallbacksBridge.java
import burp.*;
import com.redcanari.js.proxies.*;
import com.redcanari.js.wrappers.TextEditorWrapper;
import com.redcanari.swing.SwingFXUtilities;
import javafx.scene.web.WebEngine;
import netscape.javascript.JSObject;
import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.net.CookieHandler;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;

     * the extension and of Burp Suite. Saved settings can be retrieved using the method
     * {@link #loadExtensionSetting(String)}.
     *
     * @param name  The name of the setting.
     * @param value The value of the setting. If this value is {@code null} then any existing setting with the specified
     *              name will be removed.
     */
    public void saveExtensionSetting(String name, String value) {
        SwingUtilities.invokeLater(() -> burpExtenderCallbacks.saveExtensionSetting(name, value));
    }


    /**
     * This method is used to load configuration settings for the extension that were saved using the method
     * {@link #saveExtensionSetting(String, String)}.
     *
     * @param name The name of the setting.
     * @return The value of the setting, or {@code null} if no value is set.
     */
    public String loadExtensionSetting(String name) throws InterruptedException, ExecutionException, TimeoutException {
        return SwingFXUtilities.invokeAndWait(() -> burpExtenderCallbacks.loadExtensionSetting(name));
    }


    /**
     * This method is used to create a new instance of Burp's plain text editor, for the extension to use in its own UI.
     *
     * @return an instance of {@link burp.ITextEditor}
     */
    public ITextEditor createTextEditor() {
        return new TextEditorWrapper(burpExtenderCallbacks.createTextEditor());