import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javafx.scene.layout.Region;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.css.CssMetaData;
import javafx.css.SimpleStyleableObjectProperty;
import javafx.css.Styleable;
import javafx.css.StyleableObjectProperty;
import javafx.css.StyleableProperty;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Control;
import javafx.scene.control.SkinBase;

public class ToolBarSeparator extends Control {
    private static final CssMetaData<ToolBarSeparator, Paint> STROKE_META_DATA =
    new CssMetaData<ToolBarSeparator, Paint>(
        "-my-app-separator-line-color",
        javafx.css.converter.PaintConverter.getInstance(),
        Color.GREEN,
        false
    ) {
        @Override
        public StyleableProperty<Paint> getStyleableProperty(ToolBarSeparator styleable) {
            return (StyleableProperty<Paint>) styleable.strokeProperty();
        }
        @Override
        public boolean isSettable(ToolBarSeparator styleable) {
            return true;
        }
    };

    private static final List<CssMetaData<? extends Styleable, ?>> CSS_META_DATA;

    static {
        List<CssMetaData<? extends Styleable, ?>> parentMetaData = Control.getClassCssMetaData();
        List<CssMetaData<? extends Styleable, ?>> customMetaData = new ArrayList<>(parentMetaData.size() + 1);
        customMetaData.addAll(parentMetaData);
        customMetaData.add(STROKE_META_DATA);
        CSS_META_DATA = Collections.unmodifiableList(customMetaData);
    }

    private final StyleableObjectProperty<Paint> stroke;

    public ToolBarSeparator() {
        this.stroke = new SimpleStyleableObjectProperty<>(
            STROKE_META_DATA,
            this,
            "stroke"
        );

        setMinHeight(28);
        setPrefHeight(28);
        setMaxHeight(28);

        setMinWidth(5);
        setPrefWidth(5);
        setMaxWidth(5);

        setId("my-separator-unique-id");
    }

    public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaData() {
        return CSS_META_DATA;
    }

    @Override
    protected javafx.scene.control.Skin<?> createDefaultSkin() {
        applyCss();
        if (getStroke() == null) {
            setStroke(Color.BLUE);
        }
        return new ToolBarSeparatorSkin(this);
    }

    @Override
    protected double computePrefWidth(double height) {
        return Region.USE_COMPUTED_SIZE;
    }

    public final StyleableObjectProperty<Paint> strokeProperty() {
        return stroke;
    }

    public final Paint getStroke() { return strokeProperty().get(); }
    public final void setStroke(Paint value) { strokeProperty().set(value); }

    public class ToolBarSeparatorSkin extends SkinBase<ToolBarSeparator> {
        private final Canvas canvas;

        public ToolBarSeparatorSkin(ToolBarSeparator control) {
            super(control);
            this.canvas = new Canvas();
            getChildren().add(canvas);
            control.widthProperty().addListener((obs, oldVal, newVal) -> {
                draw(newVal.doubleValue(), control.getHeight());
            });
            control.heightProperty().addListener((obs, oldVal, newVal) -> {
                draw(control.getWidth(), newVal.doubleValue());
            });
            control.strokeProperty().addListener((obs, oldVal, newVal) -> {
                System.out.println("STYLE CHANGE");
                draw(control.getWidth(), control.getHeight());
            });
        }

        @Override
        protected void layoutChildren(double contentX, double contentY, double contentWidth, double contentHeight) {
            super.layoutChildren(contentX, contentY, contentWidth, contentHeight);
            canvas.setWidth(contentWidth);
            canvas.setHeight(contentHeight);
            draw(contentWidth, contentHeight);
        }

        public void draw(double width, double height) {
            GraphicsContext gc = canvas.getGraphicsContext2D();
            gc.clearRect(0, 0, width, height);

            Color color = Color.GRAY;

            Paint p = getSkinnable().getStroke();
            if (p instanceof Color) {
				Color c = (Color) p;
                color = c;
                System.out.println("*** p is Color ***");
            } else {
                System.out.println("*** p is NOT Color ***");
            }
            gc.setStroke(color);

            gc.setLineWidth(1);

            for (double i = 0; i < height; i +=3) {
                gc.strokeLine(0, i, width, i);
            }
        }
    }
} 