R6 Robot Teach Pendant

// Copyright (C) 2026 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QtQuick
import QtQuick.Controls
import QtQuick.Controls.impl
import QtQuick.Layouts
import QtQuick.Window

Rectangle {
    id: root

    required property list<real> positions
    property var waypoints: []
    property Item overlayParent: root.Window.window ? root.Window.window.contentItem : null

    signal captureWaypoint(string name, list<real> positions)
    signal deleteWaypoint(int index)
    signal jumpToWaypoint(int index)

    function openCaptureDialog() {
        if (waypointNameField) {
            waypointNameField.text = "WP" + (root.waypoints.length + 1)
        }
        captureDialog.open()
    }

    color: "transparent"

    ColumnLayout {
        anchors.fill: parent
        spacing: 0

        // Capture Bar
        Rectangle {
            Layout.fillWidth: true
            Layout.preferredHeight: 100
            color: Theme.card

            Rectangle {
                anchors.bottom: parent.bottom
                width: parent.width
                height: 1
                color: Theme.border
            }

            ColumnLayout {
                anchors.fill: parent
                anchors.margins: Theme.spacingMedium
                spacing: 8

                Label {
                    text: "Uses current joint positions"
                    color: Theme.mutedForeground
                    font.pixelSize: 12
                }

                Button {
                    Layout.fillWidth: true
                    Layout.preferredHeight: 48

                    background: Rectangle {
                        color: parent.pressed ? Theme.accent : Theme.primary
                        radius: Theme.radius
                    }

                    contentItem: RowLayout {
                        spacing: 8

                        Label {
                            text: "●"
                            color: Theme.primaryForeground
                            font.pixelSize: 20
                        }

                        Label {
                            text: "Capture Current Pose as Waypoint"
                            color: Theme.primaryForeground
                            font.pixelSize: 14
                            font.bold: true
                            Layout.fillWidth: true
                        }
                    }

                    onClicked: root.openCaptureDialog()
                }
            }
        }

        // Waypoint List Header
        Rectangle {
            Layout.fillWidth: true
            Layout.preferredHeight: 48
            color: Theme.card

            Rectangle {
                anchors.bottom: parent.bottom
                width: parent.width
                height: 1
                color: Theme.border
            }

            RowLayout {
                anchors.fill: parent
                anchors.leftMargin: Theme.spacingMedium
                anchors.rightMargin: Theme.spacingMedium

                Label {
                    text: root.waypoints.length + " waypoint"
                          + (root.waypoints.length !== 1 ? "s" : "")
                    color: Theme.foreground
                    font.pixelSize: 14
                    font.bold: true
                }

                Item {
                    Layout.fillWidth: true
                }

                Label {
                    visible: root.waypoints.length === 0
                    text: "No waypoints captured yet"
                    color: Theme.mutedForeground
                    font.pixelSize: 12
                    font.italic: true
                }
            }
        }

        // Waypoint List
        ScrollView {
            Layout.fillWidth: true
            Layout.fillHeight: true
            clip: true

            ScrollBar.vertical.policy: ScrollBar.AsNeeded
            ScrollBar.horizontal.policy: ScrollBar.AlwaysOff

            ListView {
                id: waypointList
                model: root.waypoints
                spacing: Theme.spacingSmall
                anchors.margins: Theme.spacingMedium

                delegate: Rectangle {
                    width: waypointList.width - Theme.spacingMedium * 2
                    height: 100
                    x: Theme.spacingMedium
                    color: Theme.panel
                    radius: Theme.radius
                    border.width: 1
                    border.color: Theme.border

                    RowLayout {
                        anchors.fill: parent
                        anchors.margins: 12
                        spacing: 12

                        // Drag handle
                        Rectangle {
                            Layout.preferredWidth: 24
                            Layout.fillHeight: true
                            color: "transparent"

                            ColumnLayout {
                                anchors.centerIn: parent
                                spacing: 2
                                Repeater {
                                    model: 3
                                    Rectangle {
                                        width: 16
                                        height: 2
                                        radius: 1
                                        color: Theme.mutedForeground
                                    }
                                }
                            }
                        }

                        // Waypoint info
                        ColumnLayout {
                            Layout.fillWidth: true
                            Layout.fillHeight: true
                            spacing: 4

                            Label {
                                text: modelData.name
                                color: Theme.foreground
                                font.pixelSize: 14
                                font.bold: true
                            }

                            Label {
                                property string posStr: {
                                    if (modelData.positions
                                            && modelData.positions.length > 0) {
                                        return "J: [" + modelData.positions.map(
                                                    p => p.toFixed(2)).join(
                                                    ", ") + "]"
                                    }
                                    return "No position data"
                                }
                                text: posStr
                                color: Theme.mutedForeground
                                font.family: Theme.monoFontFamily
                                font.pixelSize: 11
                                elide: Text.ElideRight
                                Layout.fillWidth: true
                            }

                            Rectangle {
                                Layout.preferredWidth: 48
                                Layout.preferredHeight: 20
                                radius: 10
                                color: Theme.success + "33"
                                border.width: 1
                                border.color: Theme.success

                                Label {
                                    anchors.centerIn: parent
                                    text: "✓ OK"
                                    color: Theme.success
                                    font.pixelSize: 10
                                    font.bold: true
                                }
                            }
                        }

                        // Action buttons
                        ColumnLayout {
                            spacing: 4

                            Button {
                                Layout.preferredWidth: 80
                                Layout.preferredHeight: 36

                                background: Rectangle {
                                    color: parent.pressed ? Theme.accent : Theme.primary
                                    radius: Theme.radius
                                }

                                contentItem: Label {
                                    text: "Jump"
                                    color: Theme.primaryForeground
                                    font.pixelSize: 12
                                    font.bold: true
                                    horizontalAlignment: Text.AlignHCenter
                                    verticalAlignment: Text.AlignVCenter
                                }

                                onClicked: root.jumpToWaypoint(index)
                            }

                            Button {
                                Layout.preferredWidth: 80
                                Layout.preferredHeight: 36

                                background: Rectangle {
                                    color: "transparent"
                                    radius: Theme.radius
                                    border.width: 1
                                    border.color: Theme.destructive
                                }

                                contentItem: Label {
                                    text: "🗑 Delete"
                                    color: Theme.destructive
                                    font.pixelSize: 11
                                    horizontalAlignment: Text.AlignHCenter
                                    verticalAlignment: Text.AlignVCenter
                                }

                                onClicked: deleteConfirmDialog.show(index)
                            }
                        }
                    }
                }
            }
        }

        // Info message
        Rectangle {
            visible: root.waypoints.length === 0
            Layout.fillWidth: true
            Layout.fillHeight: true
            color: "transparent"

            ColumnLayout {
                anchors.centerIn: parent
                spacing: 16
                IconImage {
                    source: "waypoint.svg"
                    color: Theme.mutedForeground
                    opacity: 0.3
                    Layout.alignment: Qt.AlignHCenter
                    fillMode: IconImage.Stretch
                    sourceSize: Qt.size(120, 120)
                }

                Label {
                    text: "No waypoints yet"
                    color: Theme.mutedForeground
                    font.pixelSize: 16
                    font.bold: true
                    Layout.alignment: Qt.AlignHCenter
                }

                Label {
                    text: "Capture your first waypoint using the button above"
                    color: Theme.mutedForeground
                    font.pixelSize: 13
                    Layout.alignment: Qt.AlignHCenter
                }
            }
        }

        // Note
        Rectangle {
            Layout.fillWidth: true
            Layout.preferredHeight: 48
            color: Theme.muted

            Rectangle {
                anchors.top: parent.top
                width: parent.width
                height: 1
                color: Theme.border
            }

            Label {
                anchors.centerIn: parent
                text: "⚠ Waypoints are not saved across sessions"
                color: Theme.mutedForeground
                font.pixelSize: 11
                font.italic: true
            }
        }
    }

    // Capture Dialog
    Dialog {
        id: captureDialog
        parent: overlayParent ? overlayParent : root
        anchors.centerIn: parent
        width: 500
        modal: true
        title: "New Waypoint"

        background: Rectangle {
            color: Theme.card
            radius: Theme.radius
            border.width: 1
            border.color: Theme.border
        }

        header: Rectangle {
            width: parent.width
            height: 60
            color: Theme.card
            radius: Theme.radius

            Label {
                anchors.centerIn: parent
                text: "New Waypoint"
                color: Theme.foreground
                font.pixelSize: 18
                font.bold: true
            }

            Rectangle {
                anchors.bottom: parent.bottom
                width: parent.width
                height: 1
                color: Theme.border
            }
        }

        ColumnLayout {
            width: parent.width
            spacing: Theme.spacingMedium

            Label {
                text: "Waypoint Name"
                color: Theme.foreground
                font.pixelSize: 14
            }

            TextField {
                id: waypointNameField
                Layout.fillWidth: true
                text: "WP" + (root.waypoints.length + 1)
                color: Theme.foreground
                font.pixelSize: 14
                selectByMouse: true

                background: Rectangle {
                    color: Theme.input
                    radius: Theme.radius
                    border.width: parent.activeFocus ? 2 : 1
                    border.color: parent.activeFocus ? Theme.primary : Theme.border
                }
            }

            Label {
                text: "Current Joint Positions"
                color: Theme.mutedForeground
                font.pixelSize: 12
            }

            Rectangle {
                Layout.fillWidth: true
                Layout.preferredHeight: 80
                color: Theme.panel
                radius: Theme.radius

                Label {
                    anchors.fill: parent
                    anchors.margins: 12
                    text: root.positions.length > 0 ? root.positions.map(
                                                          p => p.toFixed(
                                                              3)).join(
                                                          ", ") : "No position data available"
                    color: Theme.foreground
                    font.family: Theme.monoFontFamily
                    font.pixelSize: 11
                    wrapMode: Text.WordWrap
                }
            }
        }

        footer: RowLayout {
            spacing: 8

            Button {
                Layout.fillWidth: true
                Layout.leftMargin: 10
                text: "Cancel"

                background: Rectangle {
                    color: "transparent"
                    radius: Theme.radius
                    border.width: 1
                    border.color: Theme.border
                }

                contentItem: Label {
                    text: parent.text
                    color: Theme.foreground
                    horizontalAlignment: Text.AlignHCenter
                    verticalAlignment: Text.AlignVCenter
                }

                onClicked: captureDialog.close()
            }

            Button {
                Layout.fillWidth: true
                Layout.rightMargin: 10
                text: "Save"

                background: Rectangle {
                    color: Theme.primary
                    radius: Theme.radius
                }

                contentItem: Label {
                    text: parent.text
                    color: Theme.primaryForeground
                    font.bold: true
                    horizontalAlignment: Text.AlignHCenter
                    verticalAlignment: Text.AlignVCenter
                }

                onClicked: {

                    root.captureWaypoint(waypointNameField.text, root.positions)

                    captureDialog.close()
                }
            }
        }
    }

    // Delete Confirmation Dialog
    QtObject {
        id: deleteConfirmDialog
        property int targetIndex: -1

        function show(index) {
            targetIndex = index
            confirmDialog.open()
        }
    }

    Dialog {
        id: confirmDialog
        parent: overlayParent ? overlayParent : root

        anchors.centerIn: parent
        width: 350
        modal: true

        background: Rectangle {
            color: Theme.card
            radius: Theme.radius
            border.width: 1
            border.color: Theme.border
        }

        ColumnLayout {
            width: parent.width
            spacing: Theme.spacingMedium

            Label {
                text: "Delete Waypoint?"
                color: Theme.foreground
                font.pixelSize: 16
                font.bold: true
            }

            Label {
                text: deleteConfirmDialog.targetIndex >= 0
                      && deleteConfirmDialog.targetIndex
                      < root.waypoints.length ? "Are you sure you want to delete \"" + root.waypoints[deleteConfirmDialog.targetIndex].name + "\"?" : "Are you sure?"
                color: Theme.mutedForeground
                font.pixelSize: 13
                wrapMode: Text.WordWrap
                Layout.fillWidth: true
            }
        }

        footer: RowLayout {
            spacing: 8

            Button {
                Layout.leftMargin: 10
                Layout.fillWidth: true
                text: "Cancel"

                background: Rectangle {
                    color: "transparent"
                    radius: Theme.radius
                    border.width: 1
                    border.color: Theme.border
                }

                contentItem: Label {
                    text: parent.text
                    color: Theme.foreground
                    horizontalAlignment: Text.AlignHCenter
                    verticalAlignment: Text.AlignVCenter
                }

                onClicked: confirmDialog.close()
            }

            Button {
                Layout.rightMargin: 10
                Layout.fillWidth: true
                text: "Delete"

                background: Rectangle {
                    color: Theme.destructive
                    radius: Theme.radius
                }

                contentItem: Label {
                    text: parent.text
                    color: Theme.destructiveForeground
                    font.bold: true
                    horizontalAlignment: Text.AlignHCenter
                    verticalAlignment: Text.AlignVCenter
                }

                onClicked: {
                    root.deleteWaypoint(deleteConfirmDialog.targetIndex)
                    confirmDialog.close()
                }
            }
        }
    }
}