#!/bin/bash

# omarchy:group=transcode
# omarchy:name=
# omarchy:summary=Transcode pictures and videos for sharing
# omarchy:args=[--path path] [input] [format] [resolution]
# omarchy:examples=omarchy transcode|omarchy transcode --path ~/Downloads|omarchy transcode ~/Videos/demo.mov mp4 1080p|omarchy transcode ~/Pictures/background.heic jpg medium

set -euo pipefail

usage() {
  cat <<'EOF'
Usage:
  omarchy transcode [--path path] [input] [format] [resolution]

With no input, pick a picture or video from ~/Pictures and ~/Videos,
or only from --path when provided. Then pick the output format and resolution.

Options:
  --path path  Limit interactive fuzzy file selection to this path

Formats:
  Pictures: jpg, png
  Videos: mp4, gif

Resolutions:
  Pictures: high, medium, low
  Videos: 4k, 1080p, 720p
EOF
}

media_type() {
  local mime
  mime=$(file -b --mime-type "$1")

  case "$mime" in
  image/*) echo picture ;;
  video/*) echo video ;;
  *)
    echo "Unsupported file type: $mime" >&2
    return 1
    ;;
  esac
}

output_path() {
  local input="$1"
  local format="$2"
  local resolution="$3"
  local dir base stem

  dir=$(dirname -- "$input")
  base=$(basename -- "$input")
  stem="${base%.*}"

  printf '%s/%s-%s.%s' "$dir" "$stem" "$resolution" "$format"
}

transcode_picture() {
  local input="$1" format="$2" resolution="$3" output="$4"
  local resize

  case "$resolution" in
  high) resize='3160x>' ;;
  medium) resize='2160x>' ;;
  low) resize='1080x>' ;;
  *)
    echo "Invalid picture resolution: $resolution" >&2
    return 1
    ;;
  esac

  case "$format" in
  jpg)
    magick "$input" -resize "$resize" -quality 85 -strip "$output"
    ;;
  png)
    magick "$input" -resize "$resize" -strip -define png:compression-filter=5 \
      -define png:compression-level=9 \
      -define png:compression-strategy=1 \
      -define png:exclude-chunk=all \
      "$output"
    ;;
  *)
    echo "Invalid picture format: $format" >&2
    return 1
    ;;
  esac
}

transcode_video() {
  local input="$1" format="$2" resolution="$3" output="$4"
  local scale

  case "$resolution" in
  4k) scale='scale=-2:2160' ;;
  1080p) scale='scale=-2:1080' ;;
  720p) scale='scale=-2:720' ;;
  *)
    echo "Invalid video resolution: $resolution" >&2
    return 1
    ;;
  esac

  case "$format" in
  mp4)
    if [[ $resolution == "4k" ]]; then
      ffmpeg -i "$input" -vf "$scale" -c:v libx265 -preset slow -crf 24 -c:a aac -b:a 192k -movflags +faststart "$output"
    else
      ffmpeg -i "$input" -vf "$scale" -c:v libx264 -preset fast -crf 23 -c:a aac -b:a 192k -movflags +faststart "$output"
    fi
    ;;
  gif)
    ffmpeg -i "$input" -vf "fps=10,$scale:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" "$output"
    ;;
  *)
    echo "Invalid video format: $format" >&2
    return 1
    ;;
  esac
}

copy_to_clipboard() {
  local output="$1"
  local uri

  uri="file://$(realpath -- "$output")"
  printf '%s\n' "$uri" | wl-copy --type text/uri-list
}

main() {
  local input="" format="" resolution="" search_path=""
  local type output positional=()

  while (( $# > 0 )); do
    case "$1" in
    --path)
      shift
      (( $# > 0 )) || { echo "Missing value for --path" >&2; return 2; }
      search_path="$1"
      ;;
    --help | -h)
      usage
      return 0
      ;;
    --)
      shift
      positional+=("$@")
      break
      ;;
    --*)
      echo "Unknown option: $1" >&2
      usage >&2
      return 2
      ;;
    *)
      positional+=("$1")
      ;;
    esac
    shift
  done

  input="${positional[0]:-}"
  format="${positional[1]:-}"
  resolution="${positional[2]:-}"
  search_path="${search_path:-$HOME/Pictures:$HOME/Videos}"

  if [[ -z $input ]]; then
    input=$(omarchy-menu-file "Transcode picture or video" "$search_path" "jpg jpeg png webp gif heic avif mp4 mov m4v mkv webm avi")
  fi

  [[ -n $input ]] || return 1
  [[ -f $input ]] || { echo "File not found: $input" >&2; return 1; }

  type=$(media_type "$input")

  if [[ -z $format ]]; then
    if [[ $type == "picture" ]]; then
      format=$(omarchy-menu-select "Select format" jpg png)
    else
      format=$(omarchy-menu-select "Select format" mp4 gif)
    fi
  fi

  if [[ -z $resolution ]]; then
    if [[ $type == "picture" ]]; then
      resolution=$(omarchy-menu-select "Select resolution" high medium low)
    else
      resolution=$(omarchy-menu-select "Select resolution" 4k 1080p 720p)
    fi
  fi

  output=$(output_path "$input" "$format" "$resolution")

  if [[ $type == "video" ]]; then
    omarchy-notification-send -g  "Transcoding video…" "$(basename -- "$input") to $format ($resolution)"
    transcode_video "$input" "$format" "$resolution" "$output"
    copy_to_clipboard "$output"
    omarchy-notification-send -g  "Transcoded to $resolution $format" "Saved and copied to clipboard."
  else
    transcode_picture "$input" "$format" "$resolution" "$output"
    copy_to_clipboard "$output"
    omarchy-notification-send -g  "Transcoded to $resolution $format" "Saved and copied to clipboard."
  fi
}

main "$@"
