package se.pingstteknik.propresenter.stagedisplayviewer.util;

import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.effect.DropShadow;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.scene.text.TextAlignment;
import javafx.stage.Screen;
import javafx.stage.Stage;
import se.pingstteknik.propresenter.stagedisplayviewer.config.Property;

import java.io.File;
import java.net.MalformedURLException;

import static se.pingstteknik.propresenter.stagedisplayviewer.config.Property.*;

public class FxUtils {
    private static final Logger log = LoggerFactory.getLogger(FxUtils.class);

    public Text createLowerKey() {
        Text lowerKey = new Text();
        lowerKey.setFont(Font.font(FONT_FAMILY.toString(), FontWeight.MEDIUM, MAX_FONT_SIZE.toInt()));
        lowerKey.setFill(Color.WHITE);
        lowerKey.setWrappingWidth(getWrappingWidth());
        lowerKey.setTextAlignment(getAlignment());
        DropShadow ds = new DropShadow();
        ds.setOffsetY(0.0);
        ds.setOffsetX(0.0);
        ds.setColor(Color.BLACK);
        ds.setSpread(0.5);
        lowerKey.setEffect(ds);
        return lowerKey;
    }
    
    /**
     * Converts the String property TextAlignment to the appropriate TextAlignment.
     * @return
     */
    private TextAlignment getAlignment() {
    	try {
    		return TextAlignment.valueOf(Property.TEXT_ALIGN.toString().toUpperCase());
    	} catch(IllegalArgumentException e) {
    		log.warn(String.format(
				"Invalid TEXT_ALIGN property: %s. It should be one of (Case insensitive): Center, Right, Left, or Justify.",
				Property.TEXT_ALIGN.toString()
				), e
			);
    		// Default to center align.
    		return TextAlignment.CENTER;
    	}
    }

    public Scene createScene(Text lowerKey) {
        Rectangle2D bounds = getScreenBounds();
        Scene scene = new Scene(createRoot(lowerKey), bounds.getWidth(), bounds.getHeight());
        scene.getStylesheets().add("styles.css");
        try {
            scene.getStylesheets().add(new File("styles.css").toURI().toURL().toString());
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        return scene;
    }

    public void startOnCorrectScreen(Stage stage) {
        Rectangle2D visualBounds = getScreen().getVisualBounds();
        stage.setX(visualBounds.getMinX() + 100);
        stage.setY(visualBounds.getMinY() + 100);
    }

    private double getWrappingWidth() {
        return getScreenBounds().getWidth() * outputWidthPercentage();
    }

    private Rectangle2D getScreenBounds() {
    	// Uses property width/height if specified, or defaults to screen bounds.
    	Rectangle2D screen = getScreen().getBounds();
    	double width = Property.WIDTH.toDouble();
    	double height = Property.HEIGHT.toDouble();
    	return new Rectangle2D(screen.getMinX(), screen.getMinY(), 
			width > 0 ? width : screen.getWidth(), 
			height > 0 ? height : screen.getHeight()
		);
    }

    private Screen getScreen() {
        return OUTPUT_SCREEN.toInt() <= Screen.getScreens().size()
                ? Screen.getScreens().get(OUTPUT_SCREEN.toInt()-1)
                : Screen.getPrimary();
    }

    private double outputWidthPercentage() {
        return 0.01 * (double) OUTPUT_WIDTH_PERCENTAGE.toInt();
    }

    private GridPane createRoot(Text lowerKey) {
        GridPane root = new GridPane();
        root.setHgap(10);
        root.setVgap(10);
        if ("top".equalsIgnoreCase(VERTICAL_ALIGN.toString())) {
            root.setAlignment(Pos.TOP_CENTER);
        } else if ("center".equalsIgnoreCase(VERTICAL_ALIGN.toString())) {
            root.setAlignment(Pos.CENTER);
        } else {
            root.setAlignment(Pos.BOTTOM_CENTER);
        }
        root.setPadding(new Insets(MARGIN_TOP.toInt(), 10, MARGIN_BOTTOM.toInt(), 10));
        root.add(lowerKey, 0, 0, 2, 1);
        return root;
    }
}