import { Palette } from "std-widgets.slint";

export struct Node { x: length, y: length}

export component Graph inherits Rectangle {
    in-out property <[Node]> nodes;
    in property <Node> node_min: { x: 0px, y: 0px };
    in property <Node> node_max: { x: 100px, y: 255px };
    property <length> graph_padding: 40px;
    property <length> axis_font_size: 14px;
    // Text {
    //     x: 0;
    //     text: "Fan PWM";
    // }

    // Text {
    //     x: root.width / 2;
    //     y: root.height - self.height;
    //     text: "Temperature";
    // }

    graph := Rectangle {
        width: root.width - root.graph_padding * 2;
        height: root.height - root.graph_padding * 2;
        x: root.graph_padding;
        y: root.graph_padding;
        function scale_x_to_graph(x: length) -> length {
            ((x - node_min.x) / (node_max.x - node_min.x)) * graph.width
        }
        //
        function scale_y_to_graph(y: length) -> length {
            ((y - node_min.y) / (node_max.y - node_min.y)) * graph.height
        }
        //
        function scale_x_to_node(x: length) -> length {
            (x / graph.width) * (node_max.x - node_min.x)
        }
        //
        function scale_y_to_node(y: length) -> length {
            (y / graph.height) * (node_max.y - node_min.y)
        }
        //

        for n in 11: Path {
            viewbox-width: self.width / 1px;
            viewbox-height: self.height / 1px;
            stroke: Palette.alternate-foreground.darker(200%);
            stroke-width: 1px;
            MoveTo {
                x: scale_x_to_graph(n * 10px) / 1px;
                y: 0;
                // scale_y_to_graph(n*1px) / 1px;
            }

            LineTo {
                x: scale_x_to_graph(n * 10px) / 1px;
                y: graph.height / 1px;
                //scale_y_to_graph(n*1px) / 1px;
            }
        }

        for n in 11: Text {
            color: Palette.accent-background;
            font-size <=> root.axis_font_size;
            text: "\{n * 10}c";
            x: scale_x_to_graph(n * 10px) - self.width / 3;
            y: graph.height + 2px;
        }

        for n in 11: Path {
            viewbox-width: self.width / 1px;
            viewbox-height: self.height / 1px;
            stroke: Palette.alternate-foreground.darker(200%);
            stroke-width: 1px;
            MoveTo {
                x: 0;
                //scale_x_to_graph(n*10px) / 1px;
                y: scale_y_to_graph(n * 25.5px) / 1px;
            }

            LineTo {
                x: graph.width / 1px;
                //scale_x_to_graph(n*10px) / 1px;
                y: scale_y_to_graph(n * 25.5px) / 1px;
            }
        }

        for n in 11: Text {
            color: Palette.accent-background;
            font-size <=> root.axis_font_size;
            text: "\{n * 10}%";
            x: - self.width;
            y: graph.height - scale_y_to_graph(n * 25.5px) - self.height / 2;
        }

        for l[idx] in nodes: path := Rectangle {
            if idx + 1 != nodes.length: Path {
                viewbox-width: self.width / 1px;
                viewbox-height: self.height / 1px;
                stroke: Palette.control-foreground;
                stroke-width: 2px;
                MoveTo {
                    x: scale_x_to_graph(nodes[idx].x) / 1px;
                    y: graph.height / 1px - scale_y_to_graph(nodes[idx].y) / 1px;
                }

                LineTo {
                    x: scale_x_to_graph(nodes[idx + 1].x) / 1px;
                    y: graph.height / 1px - scale_y_to_graph(nodes[idx + 1].y) / 1px;
                }
            }
        }

        for n[idx] in nodes: Rectangle {
            states [
                pressed when touch.pressed: {
                    point.background: Palette.selection-background;
                    tip.background: Palette.selection-background;
                    tip.opacity: 1.0;
                }
                hover when touch.has-hover: {
                    point.background: Palette.accent-background;
                    tip.background: Palette.accent-background;
                    tip.opacity: 1.0;
                }
            ]
            //
            point := Rectangle {
                background: Palette.control-foreground;
                x: scale_x_to_graph(n.x) - self.width / 2;
                y: graph.height - scale_y_to_graph(n.y) - self.height / 2;
                width: 18px;
                height: self.width;
                border-radius: self.width / 2;
                property <length> pad: 1px;

                touch := TouchArea {
                    function check() {
                        if idx + 1 < nodes.length && idx > 0 {
                            if n.x + scale_x_to_node(self.mouse-x - self.pressed-x) > nodes[idx + 1].x {
                                n.x = nodes[idx + 1].x - pad;
                            } else if n.x + scale_x_to_node(self.mouse-x - self.pressed-x) < nodes[idx - 1].x {
                                n.x = nodes[idx - 1].x + pad;
                            }
                            if n.y + scale_y_to_node(self.height - self.mouse-y - self.pressed-y) > nodes[idx + 1].y {
                                n.y = nodes[idx + 1].y - pad;
                            } else if n.y + scale_y_to_node(self.height - self.mouse-y - self.pressed-y) < nodes[idx - 1].y {
                                n.y = nodes[idx - 1].y + pad;
                            }
                        } else if idx == 0 {
                            if n.x + scale_x_to_node(self.mouse-x - self.pressed-x) < 0.0 {
                                n.x = 1px;
                            } else if n.x + scale_x_to_node(self.mouse-x - self.pressed-x) > nodes[idx + 1].x {
                                n.x = nodes[idx + 1].x - pad;
                            }
                            if n.y - scale_y_to_node(self.mouse-y - self.pressed-y) < 0.0 {
                                n.y = 1px;
                            } else if n.y + scale_y_to_node(self.height - self.mouse-y - self.pressed-y) > nodes[idx + 1].y {
                                n.y = nodes[idx + 1].y - pad;
                            }
                        } else if idx == nodes.length - 1 {
                            if n.x + scale_x_to_node(self.mouse-x - self.pressed-x) > scale_x_to_node(graph.width) {
                                n.x = scale_x_to_node(graph.width - 1px);
                            } else if n.x + scale_x_to_node(self.mouse-x - self.pressed-x) < nodes[idx - 1].x {
                                n.x = nodes[idx - 1].x + pad;
                            }
                            if n.y - scale_y_to_node(self.mouse-y - self.pressed-y) > scale_y_to_node(graph.height) {
                                n.y = scale_y_to_node(graph.height - 1px);
                            } else if n.y + scale_y_to_node(self.height - self.mouse-y - self.pressed-y) < nodes[idx - 1].y {
                                n.y = nodes[idx - 1].y + pad;
                            }
                        }
                    }
                    //
                    moved => {
                        if (self.pressed) {
                            n.x += scale_x_to_node(self.mouse-x - self.pressed-x);
                            n.y -= scale_y_to_node(self.mouse-y - self.pressed-y);
                            self.check();
                            // nodes[idx] = n;
                        }
                    }

                    clicked => {
                        self.check();
                    }
                    mouse-cursor: move;
                }
            }

            tip := Rectangle {
                background: Palette.control-foreground;
                opacity: 0.3;
                x: final_x_pos();
                y: final_y_pos();
                width: label.preferred-width;
                height: label.preferred-height;
                function x_pos() -> length {
                    scale_x_to_graph(n.x) - label.preferred-width - 8px
                }
                //
                function final_x_pos() -> length {
                    if x_pos() > 0 {
                        x_pos()
                    } else {
                        x_pos() + label.preferred-width
                    }
                }
                //
                function y_pos() -> length {
                    graph.height - scale_y_to_graph(n.y) - self.height - 4px
                }
                //
                function final_y_pos() -> length {
                    if y_pos() > 0 {
                        y_pos()
                    } else {
                        y_pos() + label.preferred-height
                    }
                }
                //
                function fan_pct() -> int {
                    Math.floor(n.y / 1px) / 255 * 100
                }
                //
                label := Text {
                    color: Palette.accent-foreground;
                    font-size: 16px;
                    text: "\{Math.floor(n.x / 1px)}c, \{fan_pct()}%";
                }
            }
        }
    }
}
