#!/usr/bin/env bash
# shellcheck source=/dev/null


# Resolving symlinks
# https://github.com/rbenv/rbenv/blob/29b4da77370af0a3413dce00a72c7631302a2b25/libexec/rbenv#L31-L50
# https://github.com/sstephenson/bats/blob/master/libexec/bats
READLINK=$(type -p greadlink readlink | head -1)
[ -n "$READLINK" ] || abort "cannot find readlink - are you missing GNU coreutils?"

resolve_link() {
  $READLINK "$1"
}

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

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

  pwd
  cd "$cwd" || exit
}

SINTER_DIR="$(abs_dirname "$0")"

linters() {
  for linter in ${SINTER_DIR}/linters/*; do
    basename "$linter"
  done
}

filename() {
  basename "$1"
}

extension() {
  [[ "$1" == *.* ]] && echo "${1##*.}" || echo ""
}

shebang() {
  head -n1 "$1" | grep '^#!' | cut -d' ' -f2
}


# open/closed principle: discover linters at runtime so we don't have to
# modify this file when extending functionality with new linters.

# source each linter
for linter in ${SINTER_DIR}/linters/*; do
  . "$linter"
done


main() {
  local name extension shebang
  name="$(filename "$1")"
  extension="$(extension "$1")"
  shebang="$(shebang "$1")"
  errlog=sinter.$$.stderr

  IFS=$'\n' read -d "" -ra functions < <(declare -F)
  for fn in "${functions[@]//declare -f }"; do
    [[ "$fn" == is_* ]] && $fn "$name" "$extension" "$shebang" && {
      if "${fn/is/lint}" "$1" >/dev/null 2>$errlog; then
        [ -z "$SINTER_QUIET" ] && echo syntax ok
        rm $errlog
        exit 0
      else
        [ -z "$SINTER_QUIET" ] && echo syntax error && cat $errlog >&2
        rm $errlog
        exit 1
      fi
    }
  done

  [ -z "$SINTER_QUIET" ] && echo no linter for "$name"
  exit 2
}


case "$1" in
  --linters )
    linters
    exit
    ;;

  -q | --quiet )
    export SINTER_QUIET=1
    shift
    ;;

  * )
    ;;
esac

[ -n "$1" ] && main "$@" || echo No file specified

