#!/bin/sh
#
# fdir - A wrapper for 'find' to simplify searching for files/dirs.
#

# --- 1. Helper Functions ---

# Displays a self-contained help message
show_help() {
  echo "Usage: fdir [-l] [-d DEPTH] [-f] [-x] [-h] [directory] [fileName]"
  echo ""
  echo "Find files or directories with a simpler interface."
  echo ""
  echo "Options:"
  echo "  -l          Long listing format (ls -ld)."
  echo "  -d DEPTH    Find at exactly DEPTH (e.g., 2). Implies -type d."
  echo "  -f          Find files only."
  echo "  -x          Exact match (no wildcards)."
  echo "  -h          Show this help message."
  echo ""
  echo "Examples:"
  echo "  fdir .                # Find all directories in ."
  echo "  fdir -f . 'myFile'    # Find files named 'myFile' in ."
  echo "  fdir -l -d 2 /var     # List all dirs/files exactly 2 levels under /var"
}

# Prints an error message to stderr and exits
error() {
  echo "Error: $1" >&2
  exit "${2:-1}" # Exit with status $2, or 1 by default
}

# --- 2. Option Variable Initialization ---
doList=0
doExact=0
fileType=""
fileTypeDesc="" # Human-readable description
depth="X"

# --- 3. Argument Parsing (getopt) ---
ARGS=$(getopt d:D:fFlLxXHh "$@")
if [ $? -ne 0 ]; then
    show_help >&2
    exit 98
fi
set -- $ARGS

# --- 4. Option Processing Loop ---
while true; do
  case "$1" in
    -h|-H)
      show_help
      exit 0
      ;;
    -d|-D)
      fileType="-type d"
      fileTypeDesc="directories"
      depth=$2
      shift 2 # Consume option (-d) and argument (DEPTH)
      ;;
    -f|-F)
      fileType="-type f"
      fileTypeDesc="files"
      shift
      ;;
    -l|-L)
      doList=1
      shift
      ;;
    -x|-X)
      doExact=1
      shift
      ;;
    --)
      shift # Consume the '--'
      break # Stop option processing
      ;;
  esac
done

# --- 5. Set File Type Defaults ---
if [ -z "$fileType" ]; then
    if [ $doList -eq 1 ]; then
        fileType="-type f -o -type d"
        fileTypeDesc="files or directories"
    else
        fileType="-type d"
        fileTypeDesc="directories"
    fi
fi

# --- 6. Process Non-Option Arguments (Dir & Name) ---
dirName="."
fileName=""

if [ $# -eq 1 ]; then
    fileName="$1"
elif [ $# -ge 2 ]; then
    dirName="$1"
    fileName="$2"
fi

if [ ! -d "$dirName" ]; then
    error "$dirName is not a valid directory." 95
fi

# --- 7. Set Wildcard Default ---
if [ $doExact -eq 0 ]; then
    if [ -z "$fileName" ]; then
        fileName="*"
    else
        # Only add wildcards if the user didn't
        case "$fileName" in
            \*|\?|\[*\]) ;; # Contains wildcards, do nothing
            *) fileName="*$fileName*" ;;
        esac
    fi
fi

# --- 8. Build and Execute Find Command ---

# Base command
find_cmd="find ${dirName} ${fileType} "

# Add Depth
if [ "${depth}" != "X" ] ;
then
    # Use -mindepth and -maxdepth to find items EXACTLY at this depth
    find_cmd="${find_cmd} -mindepth ${depth} -maxdepth ${depth} "
fi

# Add File Name
if [ ! -z "${fileName}" ] ;
then
    # Use -iname (case-insensitive)
    find_cmd="${find_cmd} -iname \"${fileName}\" "
fi

# Build final command string
if [ $doList -eq 1 ]; then
    final_cmd="${find_cmd} -exec ls -ld {} \;"
		#`find ~/Sites/ -type d -iname '*drum*' -print0 | xargs -0 ls -ld

else
    final_cmd="${find_cmd} -print"
fi

# Execute and capture output
# Suppress find errors (e.g., "Permission denied") from cluttering output
output=$(eval "${final_cmd}" 2>/dev/null)

# --- 9. Check Output and Print Results ---
if [ -z "$output" ]; then
    # Print a helpful "not found" message to stderr
    echo "No results found." >&2
    echo "  Search Criteria:" >&2
    echo "    Directory: $dirName" >&2
    echo "    Pattern:   $fileName" >&2
    echo "    Type:      $fileTypeDesc" >&2
    if [ "${depth}" != "X" ]; then
        echo "    At Depth:  $depth" >&2
    fi
    exit 1 # Exit with non-zero status
else
    # Print the results to stdout
    echo "$output"
fi
