#!/usr/bin/env bash
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$PWD}")" && pwd)"
WORK_DIR="$(mktemp -d)"
trap 'rm -rf "$WORK_DIR"' EXIT

OK=0
MISS=0

say()  { printf '\033[1;36m[theme]\033[0m %s\n' "$*"; }
okay() { printf '\033[1;32m  ok  \033[0m %s\n' "$*"; OK=$((OK+1)); }
miss() { printf '\033[1;33m  ... \033[0m %s\n' "$*"; MISS=$((MISS+1)); }

command -v tar >/dev/null 2>&1  || { echo "tar is required"; exit 1; }
command -v curl >/dev/null 2>&1 || command -v wget >/dev/null 2>&1 || { echo "curl or wget is required"; exit 1; }

for arg in "$@"; do [ "$arg" = "--browser" ] && BROWSE=1; done
[ -z "${BASH_SOURCE[0]:-}" ] && [ -z "${BROWSE:-}" ] && say "running from a pipe - use: curl ... | bash -s -- --browser"

download() {
    if command -v curl >/dev/null 2>&1; then
        curl -fsSL --max-time 300 "$1" -o "$2"
    else
        wget -q --timeout=300 -O "$2" "$1"
    fi
}

localize() {
    local label="$1" src="$2" dest
    case "$src" in
        http://*|https://*|file://*)
            dest="$WORK_DIR/$label"
            download "$src" "$dest" || return 1
            printf '%s\n' "$dest"
            ;;
        *)
            [ -e "$src" ] && printf '%s\n' "$src" || return 1
            ;;
    esac
}

unpack_if_archive() {
    local src="$1" root="$WORK_DIR/extract"
    mkdir -p "$root"
    if   tar -tzf  "$src" >/dev/null 2>&1; then tar -xzf  "$src" -C "$root" || return 1
    elif tar -tJf  "$src" >/dev/null 2>&1; then tar -xJf  "$src" -C "$root" || return 1
    elif tar -tf   "$src" >/dev/null 2>&1; then tar -xf   "$src" -C "$root" || return 1
    elif command -v unzip >/dev/null 2>&1 && unzip -l "$src" >/dev/null 2>&1; then unzip -qo "$src" -d "$root" || return 1
    else return 1
    fi
    printf '%s\n' "$root"
}

archive_contains() {
    local src="$1" marker="$2"
    if   tar -tzf "$src" 2>/dev/null | grep -im1 -- "$marker" >/dev/null; then return 0
    elif tar -tJf "$src" 2>/dev/null | grep -im1 -- "$marker" >/dev/null; then return 0
    elif tar -tf  "$src" 2>/dev/null | grep -im1 -- "$marker" >/dev/null; then return 0
    elif command -v unzip >/dev/null 2>&1 && unzip -Z1 "$src" 2>/dev/null | grep -im1 -- "$marker" >/dev/null; then return 0
    fi
    return 1
}

pick_folder() {
    local folder=""
    if command -v kdialog >/dev/null 2>&1; then
        folder="$(kdialog --title 'WencesByte theme files' --getexistingdirectory "${HOME}/Downloads" 2>/dev/null || true)"
    elif command -v zenity >/dev/null 2>&1; then
        folder="$(zenity --file-selection --directory --title 'Select the folder with the theme files' --filename "${HOME}/Downloads/" 2>/dev/null || true)"
    elif command -v qarma >/dev/null 2>&1; then
        folder="$(qarma --file-selection --folder --title 'Select the folder with the theme files' 2>/dev/null || true)"
    fi
    if [ -z "$folder" ] && [ -t 0 ]; then
        read -rp "Enter the folder path that holds the downloaded theme files (Enter to skip): " folder
    fi
    [ -d "$folder" ] && printf '%s\n' "$folder"
}

locate_slot() {
    local slot="$1" dir="$2" marker="" item name lower
    case "$slot" in
        cursor)     marker="index.theme" ;;
        icons)      marker="oxygen-icons-6.2.0" ;;
        aquarelle)  marker="AquarelleDark" ;;
        darkair)    marker="metadata.desktop" ;;
        wallpapers) marker="background-1.xml" ;;
        *) return 1 ;;
    esac
    [ -d "$dir" ] || return 1
    for item in "$dir"/*; do
        [ -e "$item" ] || continue
        name="${item##*/}"
        lower="$(printf '%s\n' "$name" | tr '[:upper:]' '[:lower:]')"
        case "$slot:$lower" in
            icons:*icon*|icons:*oxygen-icons*|icons:*6.2.0*)
                printf '%s\n' "$item"; return 0
                ;;
            aquarelle:*aquarelle*)
                printf '%s\n' "$item"; return 0
                ;;
            cursor:*cursor*|cursor:*ghost*|cursor:*1197362*)
                printf '%s\n' "$item"; return 0
                ;;
            darkair:*air*|darkair:*998819*|darkair:*darkair*)
                printf '%s\n' "$item"; return 0
                ;;
            wallpapers:*cosmos*|wallpapers:*wallpaper*|wallpapers:*1161168*|wallpapers:*.jpg)
                printf '%s\n' "$item"; return 0
                ;;
        esac
    done
    for item in "$dir"/*; do
        if [ -d "$item" ]; then
            [ -e "$item/$marker" ] && { printf '%s\n' "$item"; return 0; }
        else
            archive_contains "$item" "$marker" && { printf '%s\n' "$item"; return 0; }
        fi
    done
    return 1
}

install_asset() {
    local slot="$1" url="$2" sidecars="$3" dir_src="$4" installed="$5" target="$6" marker="$7" mode="$8" display="$9"
    local side src path area ex f
    say "== $display =="
    if [ -e "$installed" ]; then
        okay "already installed at $installed"
        return
    fi
    src="${url:-}"
    for side in $sidecars; do
        [ -z "$src" ] && [ -e "$SCRIPT_DIR/$side" ] && src="$SCRIPT_DIR/$side"
    done
    [ -e "$dir_src" ] && [ -z "$src" ] && src="$dir_src"
    if [ -z "$src" ]; then
        miss "no $display source. Put its file next to this script, set the matching URL, or use --browser."
        return
    fi
    path="$(localize "$slot" "$src")" || { miss "cannot read $src"; return; }
    if [ -d "$path" ]; then
        if [ "$mode" = "replace" ]; then
            mkdir -p "$(dirname "$target")"
            rm -rf "$target"
            cp -r "$path" "$target"
        else
            mkdir -p "$target"
            cp -r "$path"/. "$target"/
        fi
        okay "installed to $target"
        return
    fi
    if ex="$(unpack_if_archive "$path")"; then
        f="$(find "$ex" -name "$marker" -type f 2>/dev/null | head -1 || true)"
        if [ -n "$f" ]; then
            area="$(dirname "$f")"
        else
            area="$ex"
        fi
        if [ "$mode" = "replace" ]; then
            mkdir -p "$(dirname "$target")"
            rm -rf "$target"
            cp -r "$area" "$target"
        else
            mkdir -p "$target"
            cp -r "$area"/. "$target"/
        fi
        okay "installed to $target"
    elif [ "$mode" = "image" ]; then
        mkdir -p "$target"
        cp "$path" "$target/comet.jpg"
        okay "installed to $target/comet.jpg"
    else
        miss "cannot unpack $src"
    fi
}

if [ "${BROWSE:-0}" = 1 ]; then
    say "Opening the KDE Store pages in your browser:"
    for url in "https://store.kde.org/p/1197362/" "https://store.kde.org/p/998819/" "https://store.kde.org/p/1161168/"; do
        say "  $url"
        if command -v xdg-open >/dev/null 2>&1; then
            ( xdg-open "$url" >/dev/null 2>&1 & )
        else
            say "  (xdg-open missing - open it manually)"
        fi
    done
    say "Download what you need in each tab, then pick the folder that contains the files."
    PICK="$(pick_folder || true)"
    if [ -z "$PICK" ]; then
        miss "no folder picked; only files next to this script will be used"
    else
        okay "scanning $PICK"
        S="$(locate_slot icons "$PICK" || true)"
        [ -n "$S" ] && { ICONS_URL="$S"; okay "icon theme: $S"; } || miss "no icon theme found in $PICK"
        S="$(locate_slot aquarelle "$PICK" || true)"
        [ -n "$S" ] && { ACQ_URL="$S"; okay "decoration: $S"; } || miss "no AquarelleDark found in $PICK"
        S="$(locate_slot cursor "$PICK" || true)"
        [ -n "$S" ] && { CURSOR_URL="$S"; okay "cursor: $S"; } || miss "no cursor found in $PICK"
        S="$(locate_slot darkair "$PICK" || true)"
        [ -n "$S" ] && { THEME_URL="$S"; okay "theme: $S"; } || miss "no Dark Air found in $PICK"
        S="$(locate_slot wallpapers "$PICK" || true)"
        [ -n "$S" ] && { WALLPAPERS_URL="$S"; okay "wallpapers: $S"; } || miss "no wallpaper pack found in $PICK"
    fi
fi

install_asset icons      "${ICONS_URL:-}" "icon-theme.tar.xz icon-theme.tar.gz icon-theme.tgz icons.tar.gz oxygen-icons-6.2.0.tar.xz" \
    "$SCRIPT_DIR/oxygen-icons-6.2.0" \
    "$HOME/.icons/oxygen-icons-6.2.0" "$HOME/.icons/oxygen-icons-6.2.0" \
    index.theme replace "Icon theme (oxygen-icons-6.2.0)"

install_asset aquarelle  "${ACQ_URL:-}" "AquarelleDark.tar.gz aquarelle.tar.gz aquarelledark.tar.gz aquarelle-dark.tar.gz" \
    "$SCRIPT_DIR/AquarelleDark" \
    "$HOME/.local/share/aurorae/themes/AquarelleDark" "$HOME/.local/share/aurorae/themes/AquarelleDark" \
    metadata.desktop replace "Window decoration (AquarelleDark)"

install_asset cursor     "${CURSOR_URL:-}" "cursors.tar.gz" \
    "$SCRIPT_DIR/cursors" \
    "$HOME/.icons/Oxygen 35 Black Ghost" "$HOME/.icons/Oxygen 35 Black Ghost" \
    index.theme replace "Cursor (Oxygen 35 Black Ghost)"

install_asset darkair    "${THEME_URL:-}" "DarkAir.tar.gz" \
    "$SCRIPT_DIR/DarkAir" \
    "$HOME/.local/share/plasma/desktoptheme/DarkAir" "$HOME/.local/share/plasma/desktoptheme/DarkAir" \
    metadata.desktop replace "Desktop theme (Dark Air)"

install_asset wallpapers "${WALLPAPERS_URL:-}" "wallpapers.tar.gz" \
    "$SCRIPT_DIR/wallpapers" \
    "$HOME/.local/share/wallpapers/cosmos/comet.jpg" "$HOME/.local/share/wallpapers/cosmos" \
    background-1.xml image "Wallpapers (cosmos, active: comet.jpg)"

install_global_theme() {
    local dir="$HOME/.local/share/plasma/look-and-feel/wencesbyte-theme"
    say "== Global theme (WencesByte's Theme) =="
    if [ -e "$dir/metadata.json" ]; then
        okay "already installed at $dir"
        return
    fi
    mkdir -p "$dir/contents"
    cat > "$dir/metadata.json" <<'EOF'
{
    "KPackageStructure": "Plasma/LookAndFeel",
    "KPlugin": {
        "Authors": [
            {
                "Name": "WencesByte"
            }
        ],
        "Category": "Plasma Look And Feel",
        "Description": "Dark Air desktop, Oxygen icons, Black Ghost cursor, Aquarelle decorations.",
        "Id": "wencesbyte-theme",
        "License": "GPLv2+",
        "Name": "WencesByte's Theme",
        "Version": "1.0"
    }
}
EOF
    cat > "$dir/contents/defaults" <<'EOF'
[kdeglobals][General]
font=Segoe UI Variable Static Display,10,-1,5,400,0,0,0,0,0,0,0,0,0,0,1

[kdeglobals][Icons]
Theme=oxygen-icons-6.2.0

[kdeglobals][KDE]
widgetStyle=Fusion

[plasmarc][Theme]
name=DarkAir

[kcminputrc][Mouse]
cursorTheme=Oxygen 35 Black Ghost
cursorSize=24

[kwinrc][org.kde.kdecoration2]
library=org.kde.kwin.aurorae.v2
theme=__aurorae__svg__AquarelleDark
EOF
    okay "installed to $dir"
    say "  Apply it in System Settings -> Global Themes."
}

install_global_theme

say "== Applying config =="
if command -v kwriteconfig6 >/dev/null 2>&1; then
    kwriteconfig6 --file kwinrc     --group org.kde.kdecoration2 --key theme __aurorae__svg__AquarelleDark
    kwriteconfig6 --file kcminputrc --group Mouse               --key cursorTheme 'Oxygen 35 Black Ghost'
    kwriteconfig6 --file kcminputrc --group Mouse               --key cursorSize 24
    kwriteconfig6 --file plasmarc   --group Theme               --key name DarkAir
    kwriteconfig6 --file kdeglobals --group KDE                 --key widgetStyle Fusion
    kwriteconfig6 --file kdeglobals --group Icons               --key Theme oxygen-icons-6.2.0 2>/dev/null || true
    kwriteconfig6 --file kdeglobals --group General             --key font 'Segoe UI Variable Static Display,10,-1,5,400,0,0,0,0,0,0,0,0,0,0,1'
    okay "theme settings written"
else
    miss "kwriteconfig6 not found - set the theme in System Settings"
fi
command -v qdbus >/dev/null 2>&1 && qdbus org.kde.KWin /KWin reconfigure >/dev/null 2>&1 || true

printf '\n'
printf '  %d installed, %d skipped\n' "$OK" "$MISS"
printf '  Restart the shell:  plasmashell --replace &   (cursor/deco may need a log out)\n'
exit 0