#!/bin/bash

# Strict mode
set -euo pipefail
IFS=$'\n\t'

BASENAME=$(basename $0)

# Global options
STYLE=singleline
PREFIX='#'


# Helper functions
# ----------------

# Prints help text
function usage {
    cat << END_OF_HELPTEXT
Usage: $BASENAME [OPTION] FILES...

Prints FILES with their filename as a header. Like cat but more cute.

General options:
  -h               print this help message

Style options:
  -b               show big headers (dashed lines above and under filename)
  -p PREFIX        use PREFIX in front of the header lines (default: '#')
END_OF_HELPTEXT
}

# Print a single file with header
function print_file_with_header {
    file=$1

    print_header $file
    print_file $file
    echo
}

# Prints a header
function print_header {
    text=$1
    
    case $STYLE in
        big)
            header_style_big "$text"
            ;;

        singleline | *)
            header_style_singleline "$text"
            ;;
    esac
}

# Print error message
function print_error {
    text=$1
    echo "$PREFIX [$text]"
}

# Prints content of file
function print_file {
    file=$1

    if [[ -f $file ]]; then
        cat $file
    elif [[ -d $file ]]; then
        print_error "File is a directory"
    else
        print_error "File does not exist"
    fi
}


# Define header styles
# --------------------

function header_style_singleline {
    text=$1
    echo "$PREFIX $text"
}

function header_style_big {
    text=$1
    length=${#text}

    echo -n "$PREFIX "; characterline '-' $length
    echo    "$PREFIX $text"
    echo -n "$PREFIX "; characterline '-' $length
}

# Print a line of characters (e.g. `characterline '#' 32`)
function characterline {
    char=$1
    count=$2

    for (( i = 0; i < $count; i++ )); do echo -n $char; done
    echo
}



# Main program
# ------------

if [[ "$@" == "--help" ]]; then
    usage
    exit 0
fi

# Parse shell arguments and set global variables
while getopts ":hbp:" option; do
    case $option in
        h)
            usage
            exit 0
            ;;

        b)
            STYLE=big
            ;;

        p)
            PREFIX="$OPTARG"
            ;;

        :)
            echo "$BASENAME: option -$OPTARG requires an argument" >&2
            echo "Try '$BASENAME --help' for more information." >&2
            exit 1
            ;;

        ?)
            echo "$BASENAME: invalid option: -$OPTARG" >&2
            echo "Try '$BASENAME --help' for more information." >&2
            exit 1
            ;;
    esac
done

# Remove parsed options from arguments
shift $(($OPTIND - 1))

# Print all files
for file in $@; do
    print_file_with_header $file
done

