package com.annimon.hotarufx.visual.objects;

import com.annimon.hotarufx.visual.PropertyBindings;
import com.annimon.hotarufx.visual.PropertyTimeline;
import com.annimon.hotarufx.visual.PropertyTimelineHolder;
import com.annimon.hotarufx.visual.TimeLine;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Shape;
import static com.annimon.hotarufx.visual.PropertyType.*;

public abstract class ShapeNode extends ObjectNode {

    private final Shape shape;

    private PropertyTimelineHolder<Boolean> smooth;
    private PropertyTimelineHolder<Paint> fill, stroke;
    private PropertyTimelineHolder<Number> strokeWidth, strokeDashOffset, strokeMiterLimit;

    public ShapeNode(Shape shape) {
        super(shape);
        this.shape = shape;
        smooth = PropertyTimelineHolder.empty();
        fill = PropertyTimelineHolder.empty();
        stroke = PropertyTimelineHolder.empty();
        strokeWidth = PropertyTimelineHolder.empty();
        strokeDashOffset = PropertyTimelineHolder.empty();
        strokeMiterLimit = PropertyTimelineHolder.empty();
    }

    public PropertyTimeline<Boolean> smoothProperty() {
        return smooth.setIfEmptyThenGet(shape::smoothProperty);
    }

    public PropertyTimeline<Paint> fillProperty() {
        return fill.setIfEmptyThenGet(shape::fillProperty);
    }

    public PropertyTimeline<Paint> strokeProperty() {
        return stroke.setIfEmptyThenGet(shape::strokeProperty);
    }

    public PropertyTimeline<Number> strokeWidthProperty() {
        return strokeWidth.setIfEmptyThenGet(shape::strokeWidthProperty);
    }

    public PropertyTimeline<Number> strokeDashOffsetProperty() {
        return strokeDashOffset.setIfEmptyThenGet(shape::strokeDashOffsetProperty);
    }

    public PropertyTimeline<Number> strokeMiterLimitProperty() {
        return strokeMiterLimit.setIfEmptyThenGet(shape::strokeMiterLimitProperty);
    }

    @Override
    public void buildTimeline(TimeLine timeline) {
        super.buildTimeline(timeline);
        smooth.applyIfPresent(timeline);
        fill.applyIfPresent(timeline);
        stroke.applyIfPresent(timeline);
        strokeWidth.applyIfPresent(timeline);
        strokeDashOffset.applyIfPresent(timeline);
        strokeMiterLimit.applyIfPresent(timeline);
    }

    @Override
    public PropertyBindings propertyBindings(PropertyBindings bindings) {
        return super.propertyBindings(bindings)
                .add("smooth", BOOLEAN, this::smoothProperty)
                .add("fill", PAINT, this::fillProperty)
                .add("stroke", PAINT, this::strokeProperty)
                .add("strokeWidth", NUMBER, this::strokeWidthProperty)
                .add("strokeDashOffset", NUMBER, this::strokeDashOffsetProperty)
                .add("strokeMiterLimit", NUMBER, this::strokeMiterLimitProperty);
    }
}

@@ -315,16 +315,137 @@
 .Shape;%0A
+import javafx.scene.shape.StrokeLineCap;%0Aimport javafx.scene.shape.StrokeLineJoin;%0Aimport javafx.scene.shape.StrokeType;%0A
 import s
@@ -494,16 +494,16 @@
 Type.*;%0A
-
 %0Apublic 
@@ -780,16 +780,102 @@
 erLimit;
+%0A    private PropertyTimelineHolder%3CString%3E strokeType, strokeLineCap, strokeLineJoin;
 %0A%0A    pu
@@ -1145,32 +1145,85 @@
 Holder.empty();%0A
+        strokeType = PropertyTimelineHolder.empty();%0A
         strokeDa
@@ -1320,24 +1320,137 @@
 er.empty();%0A
+        strokeLineCap = PropertyTimelineHolder.empty();%0A        strokeLineJoin = PropertyTimelineHolder.empty();%0A
     %7D%0A%0A    p
@@ -1948,32 +1948,203 @@
 operty);%0A    %7D%0A%0A
+    public PropertyTimeline%3CString%3E strokeTypeProperty() %7B%0A        return strokeType.setIfEmptyThenGet(enumToString(StrokeType.class, shape.strokeTypeProperty()));%0A    %7D%0A%0A
     public Prope
@@ -2431,32 +2431,402 @@
 operty);%0A    %7D%0A%0A
+    public PropertyTimeline%3CString%3E strokeLineCapProperty() %7B%0A        return strokeLineCap.setIfEmptyThenGet(enumToString(StrokeLineCap.class, shape.strokeLineCapProperty()));%0A    %7D%0A%0A    public PropertyTimeline%3CString%3E strokeLineJoinProperty() %7B%0A        return strokeLineJoin.setIfEmptyThenGet(enumToString(StrokeLineJoin.class, shape.strokeLineJoinProperty()));%0A    %7D%0A%0A
     @Override%0A  
@@ -3026,32 +3026,77 @@
 sent(timeline);%0A
+        strokeType.applyIfPresent(timeline);%0A
         strokeWi
@@ -3223,24 +3223,121 @@
 (timeline);%0A
+        strokeLineCap.applyIfPresent(timeline);%0A        strokeLineJoin.applyIfPresent(timeline);%0A
     %7D%0A%0A    @
@@ -3637,32 +3637,101 @@
 strokeProperty)%0A
+                .add(%22strokeType%22, STRING, this::strokeTypeProperty)%0A
                 
@@ -3858,32 +3858,32 @@
 OffsetProperty)%0A
-
                 
@@ -3938,26 +3938,178 @@
 erLimitProperty)
+%0A                .add(%22strokeLineCap%22, STRING, this::strokeLineCapProperty)%0A                .add(%22strokeLineJoin%22, STRING, this::strokeLineJoinProperty)
 ;%0A    %7D%0A%7D%0A

Add shape stroke enum properties