// Connections — wired, Wi-Fi, and Bluetooth.
//
// Wi-Fi and Bluetooth are handled here rather than delegated. Everything goes
// through Quickshell.Networking and Quickshell.Bluetooth -- NetworkManager and
// BlueZ over DBus -- and nothing shells out to nmcli or bluetoothctl. That was
// the founding requirement for this desktop: never having to drop to a terminal
// to join a network.
//
// Scanning follows this page being on screen. Wi-Fi scanning and especially
// Bluetooth discovery hold the radio, and doing either for a list nobody is
// looking at is battery and airtime spent on nothing.

import QtQuick
import Quickshell
import Quickshell.Networking
import qs.config
import qs.services

SettingsPage {
    id: root


    title: "Connections"
    lede: Connectivity.activeNetwork
        ? "Connected to " + Connectivity.activeNetwork.name
        : "Wi-Fi, Bluetooth, and the things Fedora owns."

    // Drive the scanners only while this page is the one being shown.
    Component.onCompleted: {
        Connectivity.active = true;
        if (!WifiShare.scanned)
            WifiShare.refresh();
    }
    Component.onDestruction: Connectivity.active = false

    SettingsCard {
        title: "Wired"
        visible: Connectivity.wiredDevice !== null

        SwitchRow {
            label: "Ethernet"
            // Three states worth telling apart: on, off but plugged in, and
            // nothing in the socket. "Not connected" covered all three and
            // explained none of them.
            detail: {
                const device = Connectivity.wiredDevice;
                if (!device)
                    return "";
                if (device.connected)
                    return device.name + (device.linkSpeed > 0
                        ? " · " + device.linkSpeed + " Mb/s" : "");
                // Not "no cable": that cannot be told apart from "switched off"
                // by anything reliable here, and guessing produced a switch
                // that blamed the hardware for what it had just done itself.
                return device.name + " · off";
            }
            checked: Connectivity.wiredOn
            enabled: Connectivity.wiredAvailable
            divider: false
            onToggled: value => Connectivity.setWired(value)
        }
    }

    SettingsCard {
        title: "Wi-Fi"
        // A Wi-Fi switch reading "On" above the words "No Wi-Fi adapter" is a
        // contradiction; with no radio the card simply does not belong.
        visible: Connectivity.wifiDevice !== null
        subtitle: "Networks are re-scanned while this page is open."

        SettingRow {
            label: "Wi-Fi"
            detail: Connectivity.wifiEnabled ? "On" : "Off"
            controlWidth: 48
            divider: Connectivity.wifiEnabled

            SettingsToggle {
                anchors.right: parent.right
                anchors.verticalCenter: parent.verticalCenter
                checked: Connectivity.wifiEnabled
                enabled: Connectivity.wifiAvailable
                onToggled: value => Networking.wifiEnabled = value
            }
        }

        WifiPanel {
            width: parent.width
            visible: Connectivity.wifiEnabled
        }
    }

    // Sharing a network by QR, the way GNOME's Wi-Fi panel does. The
    // alternative is reading a passphrase out loud.
    //
    // The image holds the password in machine-readable form, so it is generated
    // on demand rather than up front, and the helper writes it to tmpfs under
    // XDG_RUNTIME_DIR instead of anywhere persistent.
    SettingsCard {
        visible: Connectivity.wifiDevice !== null && WifiShare.shareable.length > 0
        title: "Share a network"
        subtitle: WifiShare.sharing !== ""
            ? "Point a phone's camera at the code to join " + WifiShare.sharing + "."
            : "Shows a QR code a phone can scan to join, without reading the password out."

        Repeater {
            model: WifiShare.shareable

            ActionRow {
                id: shareRow
                required property var modelData
                required property int index

                label: shareRow.modelData.ssid
                detail: WifiShare.sharing === shareRow.modelData.name
                    ? "Showing a code below — anyone who can see the screen can join"
                    : "Saved network"
                action: WifiShare.sharing === shareRow.modelData.name ? "Hide" : "Show code"
                divider: shareRow.index < WifiShare.shareable.length - 1 || WifiShare.sharing !== ""
                onTriggered: WifiShare.sharing === shareRow.modelData.name
                    ? WifiShare.stopSharing()
                    : WifiShare.share(shareRow.modelData.name)
            }
        }

        // Drawn at its natural size on a white plate: a QR code inverted or
        // tinted to match a dark theme is unreliable to scan, and this one has
        // exactly one job.
        Item {
            width: parent.width
            visible: WifiShare.sharing !== "" && WifiShare.imagePath !== ""
            implicitHeight: visible ? plate.height + 20 : 0

            Rectangle {
                id: plate
                anchors.horizontalCenter: parent.horizontalCenter
                y: 10
                width: 208
                height: 208
                radius: 10
                color: "white"

                Image {
                    anchors.centerIn: parent
                    width: 184
                    height: 184
                    smooth: false
                    fillMode: Image.PreserveAspectFit
                    cache: false
                    source: WifiShare.imagePath !== "" ? "file://" + WifiShare.imagePath : ""
                }
            }
        }
    }

    SettingsCard {
        title: "Bluetooth"
        visible: Connectivity.adapter !== null
        subtitle: "Discovery runs while this page is open."

        SettingRow {
            label: "Bluetooth"
            detail: Connectivity.adapter
                ? (Connectivity.adapter.enabled ? "On" : "Off")
                : "Unavailable"
            controlWidth: 48
            divider: !!(Connectivity.adapter && Connectivity.adapter.enabled)

            SettingsToggle {
                anchors.right: parent.right
                anchors.verticalCenter: parent.verticalCenter
                checked: !!(Connectivity.adapter && Connectivity.adapter.enabled)
                enabled: Connectivity.adapter !== null
                onToggled: value => {
                    if (Connectivity.adapter)
                        Connectivity.adapter.enabled = value;
                }
            }
        }

        BluetoothPanel {
            width: parent.width
            visible: !!(Connectivity.adapter && Connectivity.adapter.enabled)
        }
    }

    SettingsCard {
        title: "Owned by Fedora"
        // These two panels drive NetworkManager over D-Bus, which is why they
        // work in this session when most GNOME panels do not. They are split
        // because GNOME splits them: "network" is wired, VPN and proxies, and
        // does not contain Wi-Fi -- the one panel used to point everyone
        // there, so the road to a hidden SSID or eduroam ended on a page
        // without Wi-Fi on it.
        subtitle: "Wired, VPN and Wi-Fi connection editing stay with GNOME's panels, which drive the same NetworkManager this page reads. Printers and online accounts have their own pages here."

        ActionRow {
            label: "Wi-Fi networks"
            detail: "Hidden networks, enterprise (802.1X) logins, and per-network settings"
            action: "Open"
            onTriggered: SystemSettings.openGnomePanel("wifi")
        }

        ActionRow {
            label: "Network connections"
            detail: "VPN, proxies, and wired connection settings"
            action: "Open"
            divider: false
            onTriggered: SystemSettings.openGnomePanel("network")
        }

    }
}
