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

manifest="${BREEZE_ICONS_EXTRA_MANIFEST:-/usr/share/breeze-icons-extra/manifest.json}"

if [[ ! -f "$manifest" ]]; then
  echo "change-folder-icon: manifest not found at $manifest" >&2
  echo "change-folder-icon: reinstall breeze-icons-extra" >&2
  exit 1
fi

if ! command -v jq >/dev/null 2>&1; then
  echo "change-folder-icon: jq is required" >&2
  exit 1
fi

if (( $# < 3 )); then
  echo "change-folder-icon: usage: change-folder-icon color|label VALUE DIR..." >&2
  exit 1
fi

colors=()
labels=()
mapfile -t colors < <(jq -r '.colors[]' "$manifest")
mapfile -t labels < <(jq -r '.labels[]' "$manifest")

if (( ${#colors[@]} == 0 )) || (( ${#labels[@]} == 0 )); then
  echo "change-folder-icon: manifest at $manifest is empty or malformed" >&2
  exit 1
fi

action="$1"
action_value="$2"
shift 2

if [[ "$action" != "color" && "$action" != "label" ]]; then
  echo "change-folder-icon: unknown action '$action'" >&2
  exit 1
fi

# Печатает самый длинный элемент массива, совпадающий с началом строки на
# границе дефиса. Пустой вывод означает отсутствие совпадения.
match_prefix() {
  local subject="$1"
  shift
  local best="" candidate

  for candidate in "$@"; do
    if [[ "$subject" == "$candidate" || "$subject" == "$candidate-"* ]]; then
      if (( ${#candidate} > ${#best} )); then
        best="$candidate"
      fi
    fi
  done

  printf '%s' "$best"
}

# Печатает элемент массива, совпадающий со строкой целиком.
match_exact() {
  local subject="$1"
  shift
  local candidate

  for candidate in "$@"; do
    if [[ "$subject" == "$candidate" ]]; then
      printf '%s' "$candidate"
      return
    fi
  done

  printf ''
}

for dir in "$@"; do
  # Состояние живёт внутри итерации: иначе метка первой папки протекала бы
  # на последующие при выделении нескольких папок сразу.
  color=""
  label=""
  entry="${dir}/.directory"

  if [[ -f "$entry" ]] && grep -q '^Icon=folder' "$entry"; then
    icon="$(sed -n 's/^Icon=//p' "$entry" | head -1)"
    rest="${icon#folder}"
    rest="${rest#-}"

    if [[ -n "$rest" ]]; then
      color="$(match_prefix "$rest" "${colors[@]}")"

      if [[ -n "$color" ]]; then
        rest="${rest#"$color"}"
        rest="${rest#-}"
      fi

      if [[ -n "$rest" ]]; then
        label="$(match_exact "$rest" "${labels[@]}")"
      fi
    fi
  fi

  if [[ "$action" == "color" ]]; then
    color="$action_value"
  else
    label="$action_value"
  fi

  icon="folder"

  if [[ -n "$color" ]]; then
    icon+="-$color"
  fi

  if [[ -n "$label" ]]; then
    icon+="-$label"
  fi

  if [[ ! -f "$entry" ]]; then
    printf '[Desktop Entry]\nIcon=%s\n' "$icon" > "$entry"
    continue
  fi

  # Временный файл создаётся рядом с целью: замена остаётся атомарной, а
  # предсказуемое имя в общем /tmp больше не используется.
  tmp="$(mktemp "${dir}/.directory.XXXXXX")"
  chmod --reference="$entry" "$tmp"

  if grep -q '^Icon=' "$entry"; then
    sed "s|^Icon=.*|Icon=${icon}|" "$entry" > "$tmp"
  elif grep -q '^\[Desktop Entry\]' "$entry"; then
    awk -v icon="$icon" '
      { print }
      !done && /^\[Desktop Entry\]$/ { print "Icon=" icon; done = 1 }
    ' "$entry" > "$tmp"
  else
    { cat "$entry"; printf '[Desktop Entry]\nIcon=%s\n' "$icon"; } > "$tmp"
  fi

  mv -f "$tmp" "$entry"
done
