import QtQuick
import QtQuick.Shapes
import qs.Common
import qs.Services

Item {
    id: root

    required property var barWindow
    required property var axis
    required property var barConfig

    readonly property bool frameShapesBar: FrameTransitionState.effectiveFrameEnabled && barWindow.usesFrameBarChrome

    visible: !frameShapesBar

    anchors.fill: parent

    anchors.left: parent.left
    anchors.top: parent.top
    readonly property bool gothEnabled: (barConfig?.gothCornersEnabled ?? false) && !(barWindow.flattenForMaximizedWindow && barWindow.hasMaximizedToplevel)
    anchors.leftMargin: -(gothEnabled && axis.isVertical && axis.edge === "right" ? barWindow._wingR : 0)
    anchors.rightMargin: -(gothEnabled && axis.isVertical && axis.edge === "left" ? barWindow._wingR : 0)
    anchors.topMargin: -(gothEnabled && !axis.isVertical && axis.edge === "bottom" ? barWindow._wingR : 0)
    anchors.bottomMargin: -(gothEnabled && !axis.isVertical && axis.edge === "top" ? barWindow._wingR : 0)

    readonly property int barPos: barConfig?.position ?? 0
    readonly property bool isTop: barPos === SettingsData.Position.Top
    readonly property bool isBottom: barPos === SettingsData.Position.Bottom
    readonly property bool isLeft: barPos === SettingsData.Position.Left
    readonly property bool isRight: barPos === SettingsData.Position.Right

    property real wing: gothEnabled ? barWindow._wingR : 0

    Behavior on wing {
        enabled: root.width > 0 && root.height > 0
        NumberAnimation {
            duration: Theme.shortDuration
            easing.type: Easing.OutCubic
        }
    }

    property real rt: {
        if (frameShapesBar)
            return SettingsData.frameRounding;
        if (barConfig?.squareCorners ?? false)
            return 0;
        if (barWindow.flattenForMaximizedWindow && barWindow.hasMaximizedToplevel)
            return 0;
        return Theme.cornerRadius;
    }

    Behavior on rt {
        enabled: root.width > 0 && root.height > 0
        NumberAnimation {
            duration: Theme.shortDuration
            easing.type: Easing.OutCubic
        }
    }

    // M3 elevation shadow — Level 2 baseline (navigation bar), with per-bar override support
    readonly property bool hasPerBarOverride: (barConfig?.shadowIntensity ?? 0) > 0
    readonly property var elevLevel: Theme.elevationLevel2
    readonly property bool shadowEnabled: (Theme.elevationEnabled && (typeof SettingsData !== "undefined" ? (SettingsData.barElevationEnabled ?? true) : false)) || hasPerBarOverride
    readonly property string autoBarShadowDirection: isTop ? "top" : (isBottom ? "bottom" : (isLeft ? "left" : (isRight ? "right" : "top")))
    readonly property string globalShadowDirection: Theme.elevationLightDirection === "autoBar" ? autoBarShadowDirection : Theme.elevationLightDirection
    readonly property string perBarShadowDirectionMode: barConfig?.shadowDirectionMode ?? "inherit"
    readonly property string perBarManualShadowDirection: {
        switch (barConfig?.shadowDirection) {
        case "top":
        case "topLeft":
        case "topRight":
        case "bottom":
            return barConfig.shadowDirection;
        default:
            return "top";
        }
    }
    readonly property string effectiveShadowDirection: {
        if (!hasPerBarOverride)
            return globalShadowDirection;
        switch (perBarShadowDirectionMode) {
        case "autoBar":
            return autoBarShadowDirection;
        case "manual":
            return perBarManualShadowDirection === "autoBar" ? autoBarShadowDirection : perBarManualShadowDirection;
        default:
            return globalShadowDirection;
        }
    }

    // Per-bar override values (when barConfig.shadowIntensity > 0)
    readonly property real overrideBlurPx: (barConfig?.shadowIntensity ?? 0) * 0.2
    readonly property real overrideOpacity: (barConfig?.shadowOpacity ?? 60) / 100
    readonly property string overrideColorMode: barConfig?.shadowColorMode ?? "default"
    readonly property color overrideBaseColor: {
        switch (overrideColorMode) {
        case "surface":
            return Theme.surface;
        case "primary":
            return Theme.primary;
        case "secondary":
            return Theme.secondary;
        case "custom":
            return barConfig?.shadowCustomColor ?? "#000000";
        default:
            return "#000000";
        }
    }

    // Resolved values — per-bar override wins if set, otherwise use global M3 elevation
    readonly property real shadowBlurPx: hasPerBarOverride ? overrideBlurPx : (elevLevel.blurPx ?? 8)
    readonly property color shadowColor: hasPerBarOverride ? Theme.withAlpha(overrideBaseColor, overrideOpacity) : Theme.elevationShadowColor(elevLevel)
    readonly property real shadowOffsetMagnitude: hasPerBarOverride ? (overrideBlurPx * 0.5) : Theme.elevationOffsetMagnitude(elevLevel, 4, effectiveShadowDirection)
    readonly property real shadowOffsetX: Theme.elevationOffsetXFor(hasPerBarOverride ? null : elevLevel, effectiveShadowDirection, shadowOffsetMagnitude)
    readonly property real shadowOffsetY: Theme.elevationOffsetYFor(hasPerBarOverride ? null : elevLevel, effectiveShadowDirection, shadowOffsetMagnitude)

    readonly property string mainPath: {
        frameShapesBar;
        rt;
        wing;
        barWindow.flattenForMaximizedWindow;
        barWindow.hasMaximizedToplevel;
        width;
        height;
        return generatePathForPosition(width, height);
    }
    readonly property string borderFullPath: {
        frameShapesBar;
        rt;
        wing;
        width;
        height;
        return generateBorderFullPath(width, height);
    }
    readonly property string borderEdgePath: {
        frameShapesBar;
        rt;
        wing;
        width;
        height;
        return generateBorderEdgePath(width, height);
    }
    property bool mainPathCorrectShape: false
    property bool borderFullPathCorrectShape: false
    property bool borderEdgePathCorrectShape: false

    onMainPathChanged: {
        if (width > 0 && height > 0) {
            root: mainPathCorrectShape = true;
        }
    }
    onBorderFullPathChanged: {
        if (width > 0 && height > 0) {
            root: borderFullPathCorrectShape = true;
        }
    }
    onBorderEdgePathChanged: {
        if (width > 0 && height > 0) {
            root: borderEdgePathCorrectShape = true;
        }
    }

    onFrameShapesBarChanged: {
        mainPathCorrectShape = false;
        borderFullPathCorrectShape = false;
        borderEdgePathCorrectShape = false;
    }

    MouseArea {
        anchors.fill: parent
        acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
        z: -999
        onClicked: {
            const activePopout = PopoutManager.getActivePopout(barWindow.screen);
            if (activePopout) {
                if (activePopout.dashVisible !== undefined) {
                    activePopout.dashVisible = false;
                } else if (activePopout.notificationHistoryVisible !== undefined) {
                    activePopout.notificationHistoryVisible = false;
                } else {
                    activePopout.close();
                }
            }
            TrayMenuManager.closeAllMenus();
        }
    }

    ElevationShadow {
        id: barShadow
        visible: root.shadowEnabled && root.width > 0 && root.height > 0

        // Size to the bar's rectangular body, excluding gothic wing extensions
        x: root.isRight ? root.wing : 0
        y: root.isBottom ? root.wing : 0
        width: axis.isVertical ? (parent.width - root.wing) : parent.width
        height: axis.isVertical ? parent.height : (parent.height - root.wing)

        shadowEnabled: root.shadowEnabled
        level: root.hasPerBarOverride ? null : root.elevLevel
        direction: root.effectiveShadowDirection
        fallbackOffset: 4
        targetRadius: root.rt
        targetColor: barWindow._bgColor

        shadowBlurPx: root.shadowBlurPx
        shadowOffsetX: root.shadowOffsetX
        shadowOffsetY: root.shadowOffsetY
        shadowColor: root.shadowColor
    }

    Loader {
        id: barShape
        anchors.fill: parent
        active: mainPathCorrectShape
        sourceComponent: Shape {
            anchors.fill: parent
            preferredRendererType: Shape.CurveRenderer

            ShapePath {
                fillColor: barWindow._bgColor
                strokeColor: "transparent"
                strokeWidth: 0

                PathSvg {
                    path: root.mainPath
                }
            }
        }
    }

    Loader {
        id: barBorder
        anchors.fill: parent
        active: borderFullPathCorrectShape && borderEdgePathCorrectShape

        readonly property real _scale: CompositorService.getScreenScale(barWindow.screen)
        readonly property real borderThickness: Math.ceil(Math.max(1, barConfig?.borderThickness ?? 1) * _scale) / _scale
        readonly property real inset: borderThickness / 2
        readonly property string borderColorKey: barConfig?.borderColor || "surfaceText"
        readonly property color baseColor: (borderColorKey === "surfaceText") ? Theme.surfaceText : (borderColorKey === "primary") ? Theme.primary : Theme.secondary
        readonly property color borderColor: Theme.withAlpha(baseColor, barConfig?.borderOpacity ?? 1.0)
        readonly property bool showFullBorder: (barConfig?.spacing ?? 4) > 0
        sourceComponent: Shape {
            id: barBorderShape
            anchors.fill: parent
            preferredRendererType: Shape.CurveRenderer
            visible: barConfig?.borderEnabled ?? false

            ShapePath {
                fillColor: "transparent"
                strokeColor: barBorder.borderColor
                strokeWidth: barBorder.borderThickness
                joinStyle: ShapePath.RoundJoin
                capStyle: ShapePath.FlatCap

                PathSvg {
                    path: barBorder.showFullBorder ? root.borderFullPath : root.borderEdgePath
                }
            }
        }
    }

    function generatePathForPosition(w, h) {
        if (isTop)
            return generateTopPath(w, h);
        if (isBottom)
            return generateBottomPath(w, h);
        if (isLeft)
            return generateLeftPath(w, h);
        if (isRight)
            return generateRightPath(w, h);
        return generateTopPath(w, h);
    }

    function generateBorderPathForPosition() {
        if (isTop)
            return generateTopBorderPath();
        if (isBottom)
            return generateBottomBorderPath();
        if (isLeft)
            return generateLeftBorderPath();
        if (isRight)
            return generateRightBorderPath();
        return generateTopBorderPath();
    }

    function generateTopPath(w, h) {
        h = h - wing;
        const r = wing;
        const cr = rt;
        const crE = frameShapesBar ? 0 : cr;

        let d = `M ${crE} 0`;
        d += ` L ${w - crE} 0`;
        if (crE > 0)
            d += ` A ${crE} ${crE} 0 0 1 ${w} ${crE}`;
        if (r > 0) {
            d += ` L ${w} ${h + r}`;
            d += ` A ${r} ${r} 0 0 0 ${w - r} ${h}`;
            d += ` L ${r} ${h}`;
            d += ` A ${r} ${r} 0 0 0 0 ${h + r}`;
        } else {
            d += ` L ${w} ${h - cr}`;
            if (cr > 0)
                d += ` A ${cr} ${cr} 0 0 1 ${w - cr} ${h}`;
            d += ` L ${cr} ${h}`;
            if (cr > 0)
                d += ` A ${cr} ${cr} 0 0 1 0 ${h - cr}`;
        }
        d += ` L 0 ${crE}`;
        if (crE > 0)
            d += ` A ${crE} ${crE} 0 0 1 ${crE} 0`;
        d += " Z";
        return d;
    }

    function generateBottomPath(w, h) {
        const fullH = h;
        h = h - wing;
        const r = wing;
        const cr = rt;
        const crE = frameShapesBar ? 0 : cr;

        let d = `M ${crE} ${fullH}`;
        d += ` L ${w - crE} ${fullH}`;
        if (crE > 0)
            d += ` A ${crE} ${crE} 0 0 0 ${w} ${fullH - crE}`;
        if (r > 0) {
            d += ` L ${w} 0`;
            d += ` A ${r} ${r} 0 0 1 ${w - r} ${r}`;
            d += ` L ${r} ${r}`;
            d += ` A ${r} ${r} 0 0 1 0 0`;
        } else {
            d += ` L ${w} ${cr}`;
            if (cr > 0)
                d += ` A ${cr} ${cr} 0 0 0 ${w - cr} 0`;
            d += ` L ${cr} 0`;
            if (cr > 0)
                d += ` A ${cr} ${cr} 0 0 0 0 ${cr}`;
        }
        d += ` L 0 ${fullH - crE}`;
        if (crE > 0)
            d += ` A ${crE} ${crE} 0 0 0 ${crE} ${fullH}`;
        d += " Z";
        return d;
    }

    function generateLeftPath(w, h) {
        w = w - wing;
        const r = wing;
        const cr = rt;
        const crE = frameShapesBar ? 0 : cr;

        let d = `M 0 ${crE}`;
        d += ` L 0 ${h - crE}`;
        if (crE > 0)
            d += ` A ${crE} ${crE} 0 0 0 ${crE} ${h}`;
        if (r > 0) {
            d += ` L ${w + r} ${h}`;
            d += ` A ${r} ${r} 0 0 1 ${w} ${h - r}`;
            d += ` L ${w} ${r}`;
            d += ` A ${r} ${r} 0 0 1 ${w + r} 0`;
        } else {
            d += ` L ${w - cr} ${h}`;
            if (cr > 0)
                d += ` A ${cr} ${cr} 0 0 0 ${w} ${h - cr}`;
            d += ` L ${w} ${cr}`;
            if (cr > 0)
                d += ` A ${cr} ${cr} 0 0 0 ${w - cr} 0`;
        }
        d += ` L ${crE} 0`;
        if (crE > 0)
            d += ` A ${crE} ${crE} 0 0 0 0 ${crE}`;
        d += " Z";
        return d;
    }

    function generateRightPath(w, h) {
        const fullW = w;
        w = w - wing;
        const r = wing;
        const cr = rt;
        const crE = frameShapesBar ? 0 : cr;

        let d = `M ${fullW} ${crE}`;
        d += ` L ${fullW} ${h - crE}`;
        if (crE > 0)
            d += ` A ${crE} ${crE} 0 0 1 ${fullW - crE} ${h}`;
        if (r > 0) {
            d += ` L 0 ${h}`;
            d += ` A ${r} ${r} 0 0 0 ${r} ${h - r}`;
            d += ` L ${r} ${r}`;
            d += ` A ${r} ${r} 0 0 0 0 0`;
        } else {
            d += ` L ${cr} ${h}`;
            if (cr > 0)
                d += ` A ${cr} ${cr} 0 0 1 0 ${h - cr}`;
            d += ` L 0 ${cr}`;
            if (cr > 0)
                d += ` A ${cr} ${cr} 0 0 1 ${cr} 0`;
        }
        d += ` L ${fullW - crE} 0`;
        if (crE > 0)
            d += ` A ${crE} ${crE} 0 0 1 ${fullW} ${crE}`;
        d += " Z";
        return d;
    }

    function generateTopBorderPath() {
        const w = barBorder.width;
        const h = barBorder.height - wing;
        const r = wing;
        const cr = rt;

        let d = "";
        if (r > 0) {
            d = `M ${w} ${h + r}`;
            d += ` A ${r} ${r} 0 0 0 ${w - r} ${h}`;
            d += ` L ${r} ${h}`;
            d += ` A ${r} ${r} 0 0 0 0 ${h + r}`;
        } else {
            d = `M ${w} ${h - cr}`;
            if (cr > 0)
                d += ` A ${cr} ${cr} 0 0 1 ${w - cr} ${h}`;
            d += ` L ${cr} ${h}`;
            if (cr > 0)
                d += ` A ${cr} ${cr} 0 0 1 0 ${h - cr}`;
        }
        return d;
    }

    function generateBottomBorderPath() {
        const w = barBorder.width;
        const r = wing;
        const cr = rt;

        let d = "";
        if (r > 0) {
            d = `M ${w} 0`;
            d += ` A ${r} ${r} 0 0 1 ${w - r} ${r}`;
            d += ` L ${r} ${r}`;
            d += ` A ${r} ${r} 0 0 1 0 0`;
        } else {
            d = `M ${w} ${cr}`;
            if (cr > 0)
                d += ` A ${cr} ${cr} 0 0 1 ${w - cr} 0`;
            d += ` L ${cr} 0`;
            if (cr > 0)
                d += ` A ${cr} ${cr} 0 0 1 0 ${cr}`;
        }
        return d;
    }

    function generateLeftBorderPath() {
        const w = barBorder.width - wing;
        const h = barBorder.height;
        const r = wing;
        const cr = rt;

        let d = "";
        if (r > 0) {
            d = `M ${w + r} ${h}`;
            d += ` A ${r} ${r} 0 0 1 ${w} ${h - r}`;
            d += ` L ${w} ${r}`;
            d += ` A ${r} ${r} 0 0 1 ${w + r} 0`;
        } else {
            d = `M ${w - cr} ${h}`;
            if (cr > 0)
                d += ` A ${cr} ${cr} 0 0 1 ${w} ${h - cr}`;
            d += ` L ${w} ${cr}`;
            if (cr > 0)
                d += ` A ${cr} ${cr} 0 0 1 ${w - cr} 0`;
        }
        return d;
    }

    function generateRightBorderPath() {
        const h = barBorder.height;
        const r = wing;
        const cr = rt;

        let d = "";
        if (r > 0) {
            d = `M 0 ${h}`;
            d += ` A ${r} ${r} 0 0 0 ${r} ${h - r}`;
            d += ` L ${r} ${r}`;
            d += ` A ${r} ${r} 0 0 0 0 0`;
        } else {
            d = `M ${cr} ${h}`;
            if (cr > 0)
                d += ` A ${cr} ${cr} 0 0 1 0 ${h - cr}`;
            d += ` L 0 ${cr}`;
            if (cr > 0)
                d += ` A ${cr} ${cr} 0 0 1 ${cr} 0`;
        }
        return d;
    }

    function generateBorderFullPath(fullW, fullH) {
        const i = barBorder.inset;
        const r = wing;
        const cr = rt;

        if (isTop) {
            const w = fullW - i * 2;
            const h = fullH - wing - i * 2;

            let d = `M ${i + cr} ${i}`;
            d += ` L ${i + w - cr} ${i}`;
            if (cr > 0)
                d += ` A ${cr} ${cr} 0 0 1 ${i + w} ${i + cr}`;
            if (r > 0) {
                d += ` L ${i + w} ${fullH - i}`;
                d += ` A ${r} ${r} 0 0 0 ${i + w - r} ${i + h}`;
                d += ` L ${i + r} ${i + h}`;
                d += ` A ${r} ${r} 0 0 0 ${i} ${fullH - i}`;
            } else {
                d += ` L ${i + w} ${i + h - cr}`;
                if (cr > 0)
                    d += ` A ${cr} ${cr} 0 0 1 ${i + w - cr} ${i + h}`;
                d += ` L ${i + cr} ${i + h}`;
                if (cr > 0)
                    d += ` A ${cr} ${cr} 0 0 1 ${i} ${i + h - cr}`;
            }
            d += ` L ${i} ${i + cr}`;
            if (cr > 0)
                d += ` A ${cr} ${cr} 0 0 1 ${i + cr} ${i}`;
            d += " Z";
            return d;
        }

        if (isBottom) {
            const w = fullW - i * 2;
            const h = fullH - wing - i * 2;

            let d = `M ${i + cr} ${fullH - i}`;
            d += ` L ${i + w - cr} ${fullH - i}`;
            if (cr > 0)
                d += ` A ${cr} ${cr} 0 0 0 ${i + w} ${fullH - i - cr}`;
            if (r > 0) {
                d += ` L ${i + w} ${i}`;
                d += ` A ${r} ${r} 0 0 1 ${i + w - r} ${i + r}`;
                d += ` L ${i + r} ${i + r}`;
                d += ` A ${r} ${r} 0 0 1 ${i} ${i}`;
            } else {
                d += ` L ${i + w} ${i + cr}`;
                if (cr > 0)
                    d += ` A ${cr} ${cr} 0 0 0 ${i + w - cr} ${i}`;
                d += ` L ${i + cr} ${i}`;
                if (cr > 0)
                    d += ` A ${cr} ${cr} 0 0 0 ${i} ${i + cr}`;
            }
            d += ` L ${i} ${fullH - i - cr}`;
            if (cr > 0)
                d += ` A ${cr} ${cr} 0 0 0 ${i + cr} ${fullH - i}`;
            d += " Z";
            return d;
        }

        if (isLeft) {
            const w = fullW - wing - i * 2;
            const h = fullH - i * 2;

            let d = `M ${i} ${i + cr}`;
            d += ` L ${i} ${i + h - cr}`;
            if (cr > 0)
                d += ` A ${cr} ${cr} 0 0 0 ${i + cr} ${i + h}`;
            if (r > 0) {
                d += ` L ${fullW - i} ${i + h}`;
                d += ` A ${r} ${r} 0 0 1 ${i + w} ${i + h - r}`;
                d += ` L ${i + w} ${i + r}`;
                d += ` A ${r} ${r} 0 0 1 ${fullW - i} ${i}`;
            } else {
                d += ` L ${i + w - cr} ${i + h}`;
                if (cr > 0)
                    d += ` A ${cr} ${cr} 0 0 0 ${i + w} ${i + h - cr}`;
                d += ` L ${i + w} ${i + cr}`;
                if (cr > 0)
                    d += ` A ${cr} ${cr} 0 0 0 ${i + w - cr} ${i}`;
            }
            d += ` L ${i + cr} ${i}`;
            if (cr > 0)
                d += ` A ${cr} ${cr} 0 0 0 ${i} ${i + cr}`;
            d += " Z";
            return d;
        }

        if (isRight) {
            const w = fullW - wing - i * 2;
            const h = fullH - i * 2;

            let d = `M ${fullW - i} ${i + cr}`;
            d += ` L ${fullW - i} ${i + h - cr}`;
            if (cr > 0)
                d += ` A ${cr} ${cr} 0 0 1 ${fullW - i - cr} ${i + h}`;
            if (r > 0) {
                d += ` L ${i} ${i + h}`;
                d += ` A ${r} ${r} 0 0 0 ${i + r} ${i + h - r}`;
                d += ` L ${i + r} ${i + r}`;
                d += ` A ${r} ${r} 0 0 0 ${i} ${i}`;
            } else {
                d += ` L ${wing + i + cr} ${i + h}`;
                if (cr > 0)
                    d += ` A ${cr} ${cr} 0 0 1 ${wing + i} ${i + h - cr}`;
                d += ` L ${wing + i} ${i + cr}`;
                if (cr > 0)
                    d += ` A ${cr} ${cr} 0 0 1 ${wing + i + cr} ${i}`;
            }
            d += ` L ${fullW - i - cr} ${i}`;
            if (cr > 0)
                d += ` A ${cr} ${cr} 0 0 1 ${fullW - i} ${i + cr}`;
            d += " Z";
            return d;
        }

        return "";
    }

    function generateBorderEdgePath(fullW, fullH) {
        const i = barBorder.inset;
        const r = wing;
        const cr = rt;

        if (isTop) {
            const w = fullW - i * 2;
            const h = fullH - wing - i * 2;

            let d = "";
            if (r > 0) {
                d = `M ${i + w} ${i + h + r}`;
                d += ` A ${r} ${r} 0 0 0 ${i + w - r} ${i + h}`;
                d += ` L ${i + r} ${i + h}`;
                d += ` A ${r} ${r} 0 0 0 ${i} ${i + h + r}`;
            } else {
                d = `M ${i + w} ${i + h - cr}`;
                if (cr > 0)
                    d += ` A ${cr} ${cr} 0 0 1 ${i + w - cr} ${i + h}`;
                d += ` L ${i + cr} ${i + h}`;
                if (cr > 0)
                    d += ` A ${cr} ${cr} 0 0 1 ${i} ${i + h - cr}`;
            }
            return d;
        }

        if (isBottom) {
            const w = fullW - i * 2;

            let d = "";
            if (r > 0) {
                d = `M ${i + w} ${i}`;
                d += ` A ${r} ${r} 0 0 1 ${i + w - r} ${i + r}`;
                d += ` L ${i + r} ${i + r}`;
                d += ` A ${r} ${r} 0 0 1 ${i} ${i}`;
            } else {
                d = `M ${i + w} ${i + cr}`;
                if (cr > 0)
                    d += ` A ${cr} ${cr} 0 0 0 ${i + w - cr} ${i}`;
                d += ` L ${i + cr} ${i}`;
                if (cr > 0)
                    d += ` A ${cr} ${cr} 0 0 0 ${i} ${i + cr}`;
            }
            return d;
        }

        if (isLeft) {
            const w = fullW - wing - i * 2;
            const h = fullH - i * 2;

            let d = "";
            if (r > 0) {
                d = `M ${i + w + r} ${i + h}`;
                d += ` A ${r} ${r} 0 0 1 ${i + w} ${i + h - r}`;
                d += ` L ${i + w} ${i + r}`;
                d += ` A ${r} ${r} 0 0 1 ${i + w + r} ${i}`;
            } else {
                d = `M ${i + w - cr} ${i + h}`;
                if (cr > 0)
                    d += ` A ${cr} ${cr} 0 0 0 ${i + w} ${i + h - cr}`;
                d += ` L ${i + w} ${i + cr}`;
                if (cr > 0)
                    d += ` A ${cr} ${cr} 0 0 0 ${i + w - cr} ${i}`;
            }
            return d;
        }

        if (isRight) {
            const h = fullH - i * 2;

            let d = "";
            if (r > 0) {
                d = `M ${i} ${i + h}`;
                d += ` A ${r} ${r} 0 0 0 ${i + r} ${i + h - r}`;
                d += ` L ${i + r} ${i + r}`;
                d += ` A ${r} ${r} 0 0 0 ${i} ${i}`;
            } else {
                d = `M ${i + cr} ${i + h}`;
                if (cr > 0)
                    d += ` A ${cr} ${cr} 0 0 1 ${i} ${i + h - cr}`;
                d += ` L ${i} ${i + cr}`;
                if (cr > 0)
                    d += ` A ${cr} ${cr} 0 0 1 ${i + cr} ${i}`;
            }
            return d;
        }

        return "";
    }
}
