#!/usr/bin/env bash
set -e

show-help() {
  echo "Usage: $(basename "$0") [<options>] <font-patcher-script-path>" \
    "<output-dir> [<font-sources>]"
  echo ""
  echo "Generates Nerd Fonts from source fonts."
  echo ""
  echo "By default generates Nerd Font, Nerd Font Mono and Nerd Font Propo"
  echo "variants for all font files."
  echo ""
  echo "Arguments:"
  echo "  <font-patcher-script-path>  Path to font-patcher script"
  echo "  <output-dir>                Output directory for generated fonts"
  echo "  <font-sources>              Optional one or more font sources." \
    "Can be directories or files (default: current directory)"
  echo ""
  echo "Options:"
  echo "  --normal, -n / --no-normal  Generate only/skip Nerd Font variant"
  echo "  --mono, -m / --no-mono      Generate only/skip Nerd Font Mono variant"
  echo "  --propo, -p / --no-prop     Generate only/skip Nerd Font Propo variant"
  echo "  --help, -h                  Show this help message"
}

main() {
  local args=()
  local generate_normal="1"
  local generate_mono="1"
  local generate_propo="1"

  # Parsing flags
  while [[ "$#" -gt 0 ]]; do
    case $1 in
      --help | -h)
        show-help
        exit 0
        ;;
      --normal | -n)
        generate_normal="1"
        generate_mono=""
        generate_propo=""
        ;;
      --no-normal) generate_normal="" ;;
      --mono | -m)
        generate_mono="1"
        generate_normal=""
        generate_propo=""
        ;;
      --no-mono) generate_mono="" ;;
      --propo | -p)
        generate_propo="1"
        generate_normal=""
        generate_mono=""
        ;;
      --no-propo) generate_propo="" ;;
      --* | -?)
        echo "Unknown option: $1"
        exit 1
        ;;
      *)
        args+=("$1")
        ;;
    esac
    shift
  done

  local patcher="${args[0]}"
  local outputDir="${args[1]}"
  local input_sources=("${args[@]:2}")
  local sources=()

  if [[ -z "$patcher" || -z "$outputDir" ]]; then
    show-help 1>&2
    exit 1
  fi

  if [[ -z "$generate_normal" && -z "$generate_mono" && -z "$generate_propo" ]]; then
    error "No Nerd Font variants selected."
    show-help 1>&2
    exit 1
  fi

  patcher="$(abs_path "$patcher")"
  if [[ ! -f "$patcher" ]]; then
    fatal "Font patcher script not found: $patcher" 1>&2
  fi

  if ! command -v fontforge > /dev/null; then
    fatal "fontforge is not installed. Please install it first."
  fi

  if [[ ! -d "$outputDir" ]]; then
    mkdir -p "$outputDir"
  fi

  if [[ ${#input_sources[@]} -eq 0 ]]; then
    echo "===> No sources specified, searching for font files in current directory"
    while read -r line; do
      sources+=("$line")
    done < <(find-sources "$(abs_path "$(pwd)")")
    echo "===> Found ${#sources[@]} font files:"
    for src in "${sources[@]}"; do
      echo "--->   - $src"
    done
  fi

  for item in "${input_sources[@]}"; do
    if [[ -d $item ]]; then
      echo "===> Finding for font files in ${item}:"
      # If it's a directory, find sources and add to array
      while read -r line; do
        echo "--->   - $line"
        sources+=("$line")
      done < <(find-sources "$item")
    else
      # If it's not a directory, process with abs_path and add to array
      sources+=("$(abs_path "$item")")
    fi
  done

  # abort if no sources found
  if [[ ${#sources[@]} -eq 0 ]]; then
    error "No font files found"
    exit 1
  fi

  for src in "${sources[@]}"; do
    echo "===> Processing $src"

    # Nerd Font
    if [[ -n "$generate_normal" ]]; then
      echo "===> Generating Nerd Font for $src"
      fontforge -lang=py -script "$patcher" --adjust-line-height --complete \
        -out "$outputDir" "$src"
    fi

    # Nerd Font Mono
    if [[ -n "$generate_mono" ]]; then
      echo "===> Generating Nerd Font Mono for $src"
      fontforge -lang=py -script "$patcher" --adjust-line-height --complete \
        --mono \
        -out "$outputDir" "$src"
    fi

    # Nerd Font Propo
    if [[ -n "$generate_propo" ]]; then
      echo "===> Generating Nerd Font Propo for $src"
      fontforge -lang=py -script "$patcher" --adjust-line-height --complete \
        --variable-width-glyphs \
        -out "$outputDir" "$src"
    fi
  done
}

error() {
  echo "ERROR: $1" 1>&2
}

fatal() {
  error "$1"
  exit 2
}

find-sources() {
  local dir="$1"
  find "$dir" -type f \( -iname '*.ttf' -o -iname '*.otf' -o -iname '*.ttc' \)
}

abs_dirname() {
  local path="$1"
  local cwd
  cwd="$(pwd)"

  while [ -n "$path" ]; do
    cd "${path%/*}" 2> /dev/null
    local name="${path##*/}"
    path="$(resolve_link "$name" || true)"
  done

  pwd
  cd "$cwd"
}

abs_path() {
  local path="$1"
  echo "$(cd "$(abs_dirname "$path")" && pwd)/$(basename "$path")"
}

resolve_link() {
  $(type -p greadlink readlink | head -1) "$1"
}

main "$@"
