#!/usr/bin/bash
#
# The OC desktop profile, applied to the *stock* extensions' own schemas.
#
# This is the configuration half of the desktop: everything here is a stock
# extension preference, settable by hand in each extension's own prefs UI --
# this script just sets them all at once. Idempotent; run it again any time.
#
# ArcMenu layout: 'Windows' (classic two-pane) is the product default. To
# try others, re-run with OC_MENU_LAYOUT set:
#
#   OC_MENU_LAYOUT=Elementary ./apply-user.sh   # grid in a popup
#   OC_MENU_LAYOUT=Pop        ./apply-user.sh   # full-screen grid (Launchpad-like)
#   OC_MENU_LAYOUT=Redmond    ./apply-user.sh   # Windows 7 two-pane
#
# All layouts: Default Brisk Whisker GnomeMenu Mint Elementary GnomeOverview
# Redmond Unity Budgie Insider Runner Chromebook Raven Tognee Plasma Windows
# Eleven AZ Enterprise Pop
set -euo pipefail

USER_EXT_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/gnome-shell/extensions"

extension_installed() { # uuid
  local uuid="$1" data_dir
  [[ -d "$USER_EXT_DIR/$uuid" ]] && return 0

  local -a data_dirs
  IFS=: read -r -a data_dirs <<< "${XDG_DATA_DIRS:-/usr/local/share:/usr/share}"
  for data_dir in "${data_dirs[@]}"; do
    [[ -d "$data_dir/gnome-shell/extensions/$uuid" ]] && return 0
  done
  return 1
}

configure_extension() { # uuid -> success iff its files are installed
  if extension_installed "$1"; then
    return 0
  fi
  echo "warning: GNOME extension '$1' is not installed; skipping its profile settings" >&2
  return 1
}

# gsettings wrapper: zip/system extensions keep schemas next to the extension;
# only fall back to global glib schemas when no per-extension schemadir exists.
gs() { # uuid schema key value...
  local uuid="$1" schema="$2" key="$3" value="$4"
  local dir="" data_dir
  if [[ -d "$USER_EXT_DIR/$uuid/schemas" ]]; then
    dir="$USER_EXT_DIR/$uuid/schemas"
  else
    local -a data_dirs
    IFS=: read -r -a data_dirs <<< "${XDG_DATA_DIRS:-/usr/local/share:/usr/share}"
    for data_dir in "${data_dirs[@]}"; do
      if [[ -d "$data_dir/gnome-shell/extensions/$uuid/schemas" ]]; then
        dir="$data_dir/gnome-shell/extensions/$uuid/schemas"
        break
      fi
    done
  fi
  if [[ -n "$dir" ]]; then
    gsettings --schemadir "$dir" set "$schema" "$key" "$value"
  else
    gsettings set "$schema" "$key" "$value"
  fi
}

gs_reset() { # uuid schema key
  local uuid="$1" schema="$2" key="$3"
  local dir="" data_dir
  if [[ -d "$USER_EXT_DIR/$uuid/schemas" ]]; then
    dir="$USER_EXT_DIR/$uuid/schemas"
  else
    local -a data_dirs
    IFS=: read -r -a data_dirs <<< "${XDG_DATA_DIRS:-/usr/local/share:/usr/share}"
    for data_dir in "${data_dirs[@]}"; do
      if [[ -d "$data_dir/gnome-shell/extensions/$uuid/schemas" ]]; then
        dir="$data_dir/gnome-shell/extensions/$uuid/schemas"
        break
      fi
    done
  fi
  if [[ -n "$dir" ]]; then
    gsettings --schemadir "$dir" reset "$schema" "$key"
  else
    gsettings reset "$schema" "$key"
  fi
}

# Live enable list. System dconf is only a default; an existing user-db
# value wins, so the profile must merge these into the user's own list.
PRODUCT_UUIDS=(
  'dash-to-panel@jderose9.github.com'
  'arcmenu@arcmenu.com'
  'appindicatorsupport@rgcjonas.gmail.com'
  'drive-menu@gnome-shell-extensions.gcampax.github.com'
  'blur-my-shell@aunetx'
  'just-perfection-desktop@just-perfection'
  'gtk4-ding@smedius.gitlab.com'
  'clipboard-indicator@tudmotu.com'
  'opencloudos-desktop-integration@opencloudos.org'
)

gsettings_as_parse() {
  local raw="$1" item
  AS_ITEMS=()
  while [[ "$raw" =~ \'([^\']+)\' ]]; do
    item="${BASH_REMATCH[1]}"
    AS_ITEMS+=("$item")
    raw="${raw#*"${BASH_REMATCH[0]}"}"
  done
}

gsettings_as_format() {
  local formatted='[' first=1 item
  for item in "${AS_ITEMS[@]}"; do
    if (( first )); then
      first=0
    else
      formatted+=', '
    fi
    formatted+="'$item'"
  done
  formatted+=']'
  printf '%s' "$formatted"
}

gsettings_as_has() {
  local uuid="$1" item
  for item in "${AS_ITEMS[@]}"; do
    [[ "$item" == "$uuid" ]] && return 0
  done
  return 1
}

enable_product_extensions() {
  local raw uuid
  raw=$(gsettings get org.gnome.shell enabled-extensions 2>/dev/null || echo '[]')
  gsettings_as_parse "$raw"
  for uuid in "${PRODUCT_UUIDS[@]}"; do
    extension_installed "$uuid" || continue
    gsettings_as_has "$uuid" && continue
    AS_ITEMS+=("$uuid")
  done
  gsettings set org.gnome.shell enabled-extensions "$(gsettings_as_format)" || true

  raw=$(gsettings get org.gnome.shell disabled-extensions 2>/dev/null || echo '[]')
  gsettings_as_parse "$raw"
  local kept=()
  for uuid in "${AS_ITEMS[@]}"; do
    local skip=0 product
    for product in "${PRODUCT_UUIDS[@]}"; do
      [[ "$uuid" == "$product" ]] && skip=1 && break
    done
    (( skip )) && continue
    kept+=("$uuid")
  done
  AS_ITEMS=("${kept[@]}")
  gsettings set org.gnome.shell disabled-extensions "$(gsettings_as_format)" || true
}

is_product_uuid() {
  local uuid="$1" item
  for item in "${PRODUCT_UUIDS[@]}"; do
    [[ "$item" == "$uuid" ]] && return 0
  done
  return 1
}

uninstall_cleanup() {
  rm -f "${XDG_CONFIG_HOME:-$HOME/.config}/opencloudos-gnome-desktop-profile.stamp"

  local raw uuid kept=()
  raw=$(gsettings get org.gnome.shell enabled-extensions 2>/dev/null || echo '[]')
  gsettings_as_parse "$raw"
  for uuid in "${AS_ITEMS[@]}"; do
    is_product_uuid "$uuid" && continue
    kept+=("$uuid")
  done
  AS_ITEMS=("${kept[@]}")
  gsettings set org.gnome.shell enabled-extensions "$(gsettings_as_format)" || true

  # Restore D2P's own default element layout (stock show-apps button).
  if extension_installed 'dash-to-panel@jderose9.github.com'; then
    gs_reset 'dash-to-panel@jderose9.github.com' \
      org.gnome.shell.extensions.dash-to-panel panel-element-positions || true
  fi

  if extension_installed 'arcmenu@arcmenu.com'; then
    gs_reset 'arcmenu@arcmenu.com' org.gnome.shell.extensions.arcmenu menu-button-icon || true
    gs_reset 'arcmenu@arcmenu.com' org.gnome.shell.extensions.arcmenu custom-menu-button-icon || true
  fi
}

if [[ "${1:-}" == --uninstall-cleanup ]]; then
  uninstall_cleanup
  exit 0
fi

enable_product_extensions
if [[ "${1:-}" == --enable-only ]]; then
  exit 0
fi

# --- Desktop-level GNOME settings ------------------------------------------
# Window buttons on the right with minimize and maximize, the Windows
# arrangement; GNOME's default shows close only.
gsettings set org.gnome.desktop.wm.preferences button-layout \
  "'appmenu:minimize,maximize,close'"

# The companion GTK theme is packaged as orchis-oc-gtk-theme. Applied only if
# actually installed, so this
# script cannot point GTK at a theme that is not there.
if [[ -d /usr/share/themes/Orchis-OC || -d "$HOME/.themes/Orchis-OC" ]]; then
  gsettings set org.gnome.desktop.interface gtk-theme "'Orchis-OC'"
fi

# --- Dash to Panel ---------------------------------------------------------
DTP_UUID='dash-to-panel@jderose9.github.com'
DTP='org.gnome.shell.extensions.dash-to-panel'

# Bar geometry: bottom of the screen, full width, 64px tall. Uses the modern
# per-monitor panel-positions key (legacy panel-position is deprecated and
# already defaults to BOTTOM — do not set it via raw system dconf).
if configure_extension "$DTP_UUID"; then
gs $DTP_UUID $DTP panel-positions "'{\"0\":\"BOTTOM\"}'"
gs $DTP_UUID $DTP panel-sizes "'{\"0\":64}'"
gs $DTP_UUID $DTP panel-lengths "'{\"0\":100}'"
gs $DTP_UUID $DTP panel-anchors "'{\"0\":\"MIDDLE\"}'"

# Task icon spacing and the subtle hover zoom, from the owner's hand-tuned
# session (2026-07 settings audit).
gs $DTP_UUID $DTP appicon-margin 8
gs $DTP_UUID $DTP appicon-padding 4
gs $DTP_UUID $DTP animate-appicon-hover true
gs $DTP_UUID $DTP dot-position "'BOTTOM'"
# GNOME's own app menu button would be a second start button.
gs $DTP_UUID $DTP show-appmenu false

gs $DTP_UUID $DTP hide-overview-on-startup true
gs $DTP_UUID $DTP stockgs-keep-top-panel false
gs $DTP_UUID $DTP overview-click-to-exit true
gs $DTP_UUID $DTP dot-style-focused "'SOLID'"
# DASHES = a short centred dash per window, the Win11 unfocused mark;
# SEGMENTED spanned the button width and read as too long.
gs $DTP_UUID $DTP dot-style-unfocused "'DASHES'"
gs $DTP_UUID $DTP dot-size 3
gs $DTP_UUID $DTP dot-color-override true
gs $DTP_UUID $DTP dot-color-dominant false
gs $DTP_UUID $DTP focus-highlight-dominant false
# The focused pill is painted by the OC theme (rounded, Win11-style); D2P's
# own square focus highlight would double-paint underneath it.
gs $DTP_UUID $DTP focus-highlight false
# Win11 running indicators: grey for unfocused windows, accent for the focused
# one. The glue rewrites the colours per scheme; these seed the light values.
gs $DTP_UUID $DTP dot-color-unfocused-different true

# The integration extension applies these colours from the generated theme
# tokens on enable and on every scheme change. Keeping no profile baseline
# avoids a second, drifting colour source.

# Hide Dash to Panel's own show-apps button: ArcMenu is the start button.
# Uninstall resets this key so the stock GNOME app-grid icon comes back.
# Per-monitor JSON, monitor 0; extra monitors fall back to D2P defaults.
# Keep ArcMenu, the search box, Activities, and task icons grouped from the
# left edge rather than in a Windows-style centred cluster. Weather is added
# by the glue extension to rightBox before the existing right-side controls.
gs $DTP_UUID $DTP panel-element-positions "'{\"0\":[{\"element\":\"leftBox\",\"visible\":true,\"position\":\"stackedTL\"},{\"element\":\"activitiesButton\",\"visible\":true,\"position\":\"stackedTL\"},{\"element\":\"taskbar\",\"visible\":true,\"position\":\"stackedTL\"},{\"element\":\"showAppsButton\",\"visible\":false,\"position\":\"stackedTL\"},{\"element\":\"centerBox\",\"visible\":false,\"position\":\"centered\"},{\"element\":\"rightBox\",\"visible\":true,\"position\":\"stackedBR\"},{\"element\":\"dateMenu\",\"visible\":true,\"position\":\"stackedBR\"},{\"element\":\"systemMenu\",\"visible\":true,\"position\":\"stackedBR\"},{\"element\":\"desktopButton\",\"visible\":true,\"position\":\"stackedBR\"}]}'"

# Translucency as an explicit value rather than theme sampling, so the bar
# looks right regardless of when the theme loads relative to the panel.
# trans-use-custom-bg is forced OFF: a custom background colour left behind by
# hand-tuning in D2P's prefs bypasses the theme entirely and reads as a solid
# bar -- exactly the "not transparent" report this line exists to prevent.
gs $DTP_UUID $DTP trans-use-custom-bg false
gs $DTP_UUID $DTP trans-use-custom-opacity true
gs $DTP_UUID $DTP trans-panel-opacity 0.70
fi

# --- Blur my Shell ---------------------------------------------------------
# Panel blur defaults ON and paints an opaque frosted layer over D2P's
# translucency (product-rejected). Overview blur keeps its default.
# Must be set via gsettings --schemadir (not system dconf local.d).
BMS_UUID='blur-my-shell@aunetx'
if configure_extension "$BMS_UUID"; then
  gs $BMS_UUID org.gnome.shell.extensions.blur-my-shell.panel blur false
fi

# --- Just Perfection -------------------------------------------------------
# startup-status defaults to 1 (overview) and overrides D2P
# hide-overview-on-startup during shell start. 0 = land on the desktop.
# Schema type is int32; never write uint32 via raw dconf — gsettings ignores it.
JP_UUID='just-perfection-desktop@just-perfection'
if configure_extension "$JP_UUID"; then
  gs $JP_UUID org.gnome.shell.extensions.just-perfection startup-status 0
fi

# --- ArcMenu ---------------------------------------------------------------
ARC_UUID='arcmenu@arcmenu.com'
ARC='org.gnome.shell.extensions.arcmenu'

# 'Windows' is the layout the owner settled on after trying Eleven -- the
# classic two-pane start menu rather than Eleven's pinned grid.
if configure_extension "$ARC_UUID"; then
gs $ARC_UUID $ARC menu-layout "'${OC_MENU_LAYOUT:-Windows}'"
gs $ARC_UUID $ARC multi-monitor false
gs $ARC_UUID $ARC override-menu-theme false
gs $ARC_UUID $ARC menu-button-appearance "'Icon'"
# Round the menu's own search entry to match the bar's capsule search box.
gs $ARC_UUID $ARC search-entry-border-radius "(true, 25)"
# The start button at stock size disappears next to 24px task icons, and sat
# flush against the screen edge; sized to match the bar's other elements.
gs $ARC_UUID $ARC custom-menu-button-icon-size 40.0
gs $ARC_UUID $ARC button-padding 4

# ArcMenu's own logo is the start-button mark; do not override it.
gs $ARC_UUID $ARC menu-button-icon "'Menu_Icon'"
gs $ARC_UUID $ARC arc-menu-icon 0
fi

echo "profile applied (menu layout: ${OC_MENU_LAYOUT:-Windows})"
