package be.iminds.ilabt.jfed.experimenter_gui.ui.code;

import javafx.scene.layout.StackPane;
import javafx.scene.text.FontSmoothingType;
import javafx.scene.web.WebView;
import org.apache.commons.lang.StringEscapeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Objects;

/**
 * User: twalcari
 * Date: 2/6/14
 * Time: 9:18 AM
 */
public class GroovyCodeView extends StackPane {
    private static final Logger LOG = LoggerFactory.getLogger(GroovyCodeView.class);
    private final WebView webView = new WebView();
    /**
     * a template for editing code - this can be changed to any template derived from the
     * supported modes at http://codemirror.net to allow syntax highlighted editing of
     * a wide variety of languages.
     */
    private final String editingTemplate =
            "<!doctype html>" +
                    "<html>" +
                    "<head>" +
                    "  <link rel=\"stylesheet\" href=\"" + GroovyCodeView.class.getResource("codemirror.css").toExternalForm() + "\">" +
                    "  <link rel=\"stylesheet\" href=\"" + GroovyCodeView.class.getResource("dialog.css").toExternalForm() + "\">" +
                    "  <link rel=\"stylesheet\" href=\"" + GroovyCodeView.class.getResource("matchesonscrollbar.css").toExternalForm() + "\">" +
                    "  <script src=\"" + GroovyCodeView.class.getResource("codemirror.js").toExternalForm() + "\"></script>" +
                    "  <script src=\"" + GroovyCodeView.class.getResource("dialog.js").toExternalForm() + "\"></script>" +
                    "  <script src=\"" + GroovyCodeView.class.getResource("jump-to-line.js").toExternalForm() + "\"></script>" +
                    "  <script src=\"" + GroovyCodeView.class.getResource("match-highlighter.js").toExternalForm() + "\"></script>" +
                    "  <script src=\"" + GroovyCodeView.class.getResource("matchesonscrollbar.js").toExternalForm() + "\"></script>" +
                    "  <script src=\"" + GroovyCodeView.class.getResource("search.js").toExternalForm() + "\"></script>" +
                    "  <script src=\"" + GroovyCodeView.class.getResource("searchcursor.js").toExternalForm() + "\"></script>" +
                    "  <script src=\"" + GroovyCodeView.class.getResource("groovy.js").toExternalForm() + "\"></script>" +
                    "</head>" +
                    "<body>" +
                    "<form><textarea id=\"code\" name=\"code\" class=\"code\">\n" +
                    "${code}" +
                    "</textarea></form>" +
                    "<script>" +
                    "  var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {" +
                    "    lineNumbers: true," +
                    "    htmlMode: false," +
                    "    lineWrapping: true," +
                    "    autofocus: true," +
                    "    readOnly: ${readOnly}," +
                    "    mode: \"text/x-groovy\"," +
                    "    viewportMargin: Infinity"  +
                    "  });" +
                    "</script>" +
                    "</body>" +
                    "</html>";

    //instance initializer
    {
        //FEDIBBTDEV-668 force smoothing to gray to prevent "washed-out" look on Mac
        webView.setFontSmoothingType(FontSmoothingType.LCD);

        getChildren().add(webView);
    }

    private String content;
    private boolean editable = true;

    public GroovyCodeView() {
        this(null);
    }

    public GroovyCodeView(String content) {
        this(content, true);
    }

    public GroovyCodeView(String content, boolean editable) {
        this.content = content;
        this.editable = editable;

        updateView();
    }

    public boolean isEditable() {
        return editable;
    }

    public void setEditable(boolean editable) {
        this.editable = editable;
        updateView();
    }

    private void updateView() {
        String editorContent = editingTemplate
                .replace("${code}", content != null ? StringEscapeUtils.escapeHtml(content) : "")
                .replace("${readOnly}", editable ? "false" : "true");

        webView.getEngine().loadContent(editorContent);
    }

    public String getContent() {
        //only get content after loadworker of webview is finished
        if (webView.getEngine().getLoadWorker().isRunning())
            return content;
        else {
            return (String) webView.getEngine().executeScript("editor.getValue();");
        }
    }

    public void setContent(String content) {
        this.content = content;
        updateView();

    }

    public void showSearch() {
        webView.getEngine().executeScript("CodeMirror.commands.find(editor);");
    }

    public void showReplace() {
        webView.getEngine().executeScript("CodeMirror.commands.replace(editor);");
    }

    public boolean isDirty() {
        return !Objects.equals(getContent(), content);
    }
}
