pragma ComponentBehavior: Bound

import Quickshell
import QtQuick
import QtQuick.Layouts
import ZShell.Config
import qs.Modules.Bar.Components
import qs.Modules.Bar.Popouts

GridLayout {
	id: root

	required property bool fullscreen
	required property bool horizontal
	required property bool isHovered
	required property Wrapper popouts
	required property ClipWrapper popoutsWrapper
	required property ShellScreen screen
	readonly property int vPadding: 6
	required property PersistentProperties visibilities

	function axisCenterOf(item: Item): real {
		const c = item.mapToItem(root, item.implicitWidth / 2, item.implicitHeight / 2);
		return horizontal ? c.x : c.y;
	}

	function checkPopout(pos: real): void {
		const ch = (horizontal ? childAt(pos, height / 2) : childAt(width / 2, pos)) as EntryWrapper;
		const id = ch?.entryId;

		if (!ch || id === undefined) {
			if (!popouts.currentName.startsWith("traymenu") || Config.bar.tray.showOnHover)
				popouts.hasCurrent = false;
			return;
		}

		if (visibilities.sidebar || visibilities.dashboard || visibilities.resources || visibilities.settings)
			return;

		if (id === "statusIcons" && Config.bar.popouts.statusIcons) {
			const items = (ch.item as StatusIcons).items;
			const icon = horizontal ? items.childAt(mapToItem(items, pos, 0).x, items.height / 2) : items.childAt(items.width / 2, mapToItem(items, 0, pos).y);
			if (icon) {
				popouts.currentName = icon.name;
				popouts.currentCenter = Qt.binding(() => axisCenterOf(icon));
				popouts.hasCurrent = true;
			}
		} else if (id === "tray" && Config.bar.popouts.tray && Config.bar.tray.showOnHover) {
			const tray = ch.item as TrayIcons;
			const layout = tray.layout;
			const trayItem = horizontal ? layout.childAt(mapToItem(layout, pos, 0).x, layout.height / 2) : layout.childAt(tray.width / 2, mapToItem(layout, 0, pos).y);

			if (trayItem) {
				const idx = trayItem.index;
				popouts.currentName = `traymenu${idx}`;
				popouts.currentCenter = Qt.binding(() => axisCenterOf(trayItem));
				popouts.hasCurrent = true;
			}

			if (!popouts.currentName.startsWith("traymenu"))
				popouts.hasCurrent = false;
		}

		if (id === "updates") {
			popouts.currentName = "updates";
			popouts.currentCenter = Qt.binding(() => axisCenterOf(ch.item as Item));
			popouts.hasCurrent = true;
		}
	}

	function entryAt(pos: real): string {
		const ch = (horizontal ? childAt(pos, height / 2) : childAt(width / 2, pos)) as EntryWrapper;
		return ch?.entryId ?? "";
	}

	columnSpacing: Tokens.spacing.small
	columns: horizontal ? -1 : 1
	rowSpacing: Tokens.spacing.small

	Repeater {
		id: repeater

		model: ScriptModel {
			values: Config.bar.entries.values.filter(e => e.enabled)
		}

		DelegateChooser {
			role: "id"

			DelegateChoice {
				roleValue: "hyprsunset"

				delegate: EntryWrapper {
					HyprsunsetWidget {
						horizontal: root.horizontal
						visible: !root.fullscreen || root.isHovered
					}
				}
			}

			DelegateChoice {
				roleValue: "spacer"

				delegate: EntryWrapper {
					Layout.fillHeight: !root.horizontal
					Layout.fillWidth: root.horizontal
				}
			}

			DelegateChoice {
				roleValue: "workspaces"

				delegate: EntryWrapper {
					Workspaces {
						horizontal: root.horizontal
						screen: root.screen
						visible: !root.fullscreen || root.isHovered
					}
				}
			}

			DelegateChoice {
				roleValue: "tray"

				delegate: EntryWrapper {
					TrayIcons {
						horizontal: root.horizontal
						loader: root
						popouts: root.popouts
						visible: !root.fullscreen || root.isHovered
					}
				}
			}

			DelegateChoice {
				roleValue: "statusIcons"

				delegate: EntryWrapper {
					StatusIcons {
						horizontal: root.horizontal
						visible: !root.fullscreen || root.isHovered
					}
				}
			}

			DelegateChoice {
				roleValue: "resources"

				delegate: EntryWrapper {
					Resources {
						horizontal: root.horizontal
						visibilities: root.visibilities
						visible: !root.fullscreen || root.isHovered
					}
				}
			}

			DelegateChoice {
				roleValue: "updates"

				delegate: EntryWrapper {
					UpdatesWidget {
						horizontal: root.horizontal
						visible: !root.fullscreen || root.isHovered
					}
				}
			}

			DelegateChoice {
				roleValue: "notifBell"

				delegate: EntryWrapper {
					NotifBell {
						horizontal: root.horizontal
						popouts: root.popouts
						visibilities: root.visibilities
						visible: !root.fullscreen || root.isHovered
					}
				}
			}

			DelegateChoice {
				roleValue: "clock"

				delegate: EntryWrapper {
					Clock {
						horizontal: root.horizontal
						loader: root
						popouts: root.popouts
						visibilities: root.visibilities
						visible: !root.fullscreen || root.isHovered
					}
				}
			}

			DelegateChoice {
				roleValue: "activeWindow"

				delegate: EntryWrapper {
					WindowTitle {
						bar: root
						horizontal: root.horizontal
						visible: !root.fullscreen || root.isHovered
					}
				}
			}

			DelegateChoice {
				roleValue: "network"

				delegate: EntryWrapper {
					NetworkWidget {
					}
				}
			}

			DelegateChoice {
				roleValue: "media"

				delegate: EntryWrapper {
					MediaWidget {
						horizontal: root.horizontal
						visible: !root.fullscreen || root.isHovered
					}
				}
			}
		}
	}

	component EntryWrapper: Item {
		readonly property string entryId: modelData.id
		required property int index
		default property Item item
		required property var modelData

		Layout.alignment: root.horizontal ? Qt.AlignVCenter : Qt.AlignHCenter
		Layout.bottomMargin: !root.horizontal && index === repeater.count - 1 ? root.vPadding : 0
		Layout.leftMargin: root.horizontal && index === 0 ? root.vPadding : (entryId === "statusIcons" && root.horizontal) ? -root.rowSpacing + Tokens.spacing.extraSmall : 0
		Layout.rightMargin: root.horizontal && index === repeater.count - 1 ? root.vPadding : 0
		Layout.topMargin: !root.horizontal && index === 0 ? root.vPadding : (entryId === "statusIcons" && !root.horizontal) ? -root.columnSpacing + Tokens.spacing.extraSmall : 0
		children: item
		implicitHeight: item?.implicitHeight ?? 0
		implicitWidth: item?.implicitWidth ?? 0
	}
}
