package nl.utwente.viskell.ui.components;

import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.layout.Pane;
import nl.utwente.viskell.ghcj.GhciSession;
import nl.utwente.viskell.haskell.expr.Expression;
import nl.utwente.viskell.haskell.type.TypeScope;
import nl.utwente.viskell.ui.CustomUIPane;
import java.util.List;

/**
 * DisplayBlock is an extension of {@link Block} that only provides a display of
 * the input it receives through it's {@link InputAnchor}. The input will be
 * rendered visually on the Block. DisplayBlock can be empty and contain no
 * value at all, the value can be altered at any time by providing a different
 * input source using a {@link Connection}.
 */
public class DisplayBlock extends Block {

    /** The Anchor that is used as input. */
    protected InputAnchor inputAnchor;

    /** The space containing the input anchor. */
    @FXML protected Pane inputSpace;

    /** The label on which to display type information. */
    @FXML protected Label inputType;
    
    /** The label on which to display the value of this block */
    @FXML protected Label value;
    
    /**
     * Creates a new instance of DisplayBlock.
     * @param pane
     *            The pane on which this DisplayBlock resides.
     */
    public DisplayBlock(CustomUIPane pane) {
        this(pane, "DisplayBlock");
    }
    
    protected DisplayBlock(CustomUIPane pane, String fxml) {
        super(pane);

        loadFXML(fxml);

        inputAnchor = new InputAnchor(this);
        inputSpace.getChildren().add(inputAnchor);
    }

    @Override
    public void invalidateVisualState() {
        if (inputAnchor.hasConnection()) {
            this.inputType.setText(this.inputAnchor.getStringType());

            GhciSession ghci = getPane().getGhciSession();

            ListenableFuture<String> result = ghci.pull(inputAnchor.getFullExpr());

            Futures.addCallback(result, new FutureCallback<String>() {
                public void onSuccess(String s) {
                    // Can't call setOutput directly - this may not be JavaFX app thread.
                    // Instead, schedule setting the output.
                    Platform.runLater(() -> value.setText(s));
                }

                public void onFailure(Throwable throwable) {
                    Platform.runLater(() -> value.setText("?!?!?!"));
                }
            });
        } else {
            inputType.setText("a");
            value.setText("?");
        }
    }
    
    //TODO NOTE: only used for a meaningless test
    public String getOutput() {
        return value.getText();
    }
    
    @Override
    public List<InputAnchor> getAllInputs() {
        return ImmutableList.of(inputAnchor);
    }

    @Override
    public List<OutputAnchor> getAllOutputs() {
        return ImmutableList.of();
    }
    
    @Override
    public Expression getLocalExpr() {
        return inputAnchor.getLocalExpr();
    }
    
    @Override
    public void refreshAnchorTypes() {
        this.inputAnchor.setFreshRequiredType(TypeScope.unique("any"), new TypeScope());        
    }

    @Override
    public String toString() {
        return "DisplayBlock[" + value.getText() + "]";
    }

}

@@ -1884,55 +1884,8 @@
 ) %7B%0A
-        if (inputAnchor.hasConnection()) %7B%0A    
     
@@ -1943,24 +1943,67 @@
 ngType());%0A%0A
+        if (inputAnchor.hasConnection()) %7B%0A
             
@@ -2675,44 +2675,8 @@
 e %7B%0A
-            inputType.setText(%22a%22);%0A
     
@@ -3280,29 +3280,62 @@
 ype(
-TypeScope.unique(%22any
+this.getPane().getEnvInstance().buildType(%22Show a =%3E a
 %22), 

Add show constraint to the input of display blocks