#!/bin/bash

export PATH=@PATH@:$PATH

export FONTCONFIG_FILE="@FONTCONFIG_FILE@"
ENCODINGSDIR="@ENCODINGSDIR@"
FC_LOCKFILE=""

# Are we caching system fonts or user fonts?
system=0

# Are we including OSX font dirs ({/,~/,/System/}Library/Fonts)
osxfonts=1

# Do we want to force a recache?
force=0

# How noisy are we?
verbose=0

# Check if the data in the given directory is newer than its cache
check_dirty() {
    local dir=$1
    local fontfiles=""
    local retval=1

    # If the dir does not exist, we just exit
    if [[ ! -d "${dir}" ]]; then
        return 1
    fi

    # Create a list of all files in the dir
    # Filter out config / cache files.  Ugly... counting down the day until
    # xfs finally goes away
    fontfiles="$(find ${dir}/ -maxdepth 1 -type f | awk '$0 !~ /fonts\..*$|^.*\.dir$/ {print}')"

    # Fonts were deleted (or never there).  Kill off the caches
    if [[ -z "${fontfiles}" ]] ; then
        local f
        for f in "${dir}"/fonts.* "${dir}"/encodings.dir; do
            if [[ -f ${f} ]] ; then
                rm -f "${f}"
            fi
        done
        return 1
    fi

    # Force a recache
    if [[ ${force} == 1 ]] ; then
        retval=0
    fi

    # If we don't have our caches, we are dirty
    if [[ ! -f "${dir}/fonts.list" || ! -f "${dir}/fonts.dir" || ! -f "${dir}/encodings.dir" ]]; then
        retval=0
    fi

    # Check that no files were added or removed....
    if [[ "${retval}" -ne 0 && "$(cat ${dir}/fonts.list)" != "${fontfiles}" ]] ; then
        retval=0
    fi

    # Check that no files were updated....
    if [[ "${retval}" -ne 0 ]] ; then
        local changed="$(find ${dir}/ -type f -cnewer ${dir}/fonts.dir | awk '$0 !~ /fonts\..*$|^.*\.dir$/ {print}')"

        if [[ -n "${changed}" ]] ; then
            retval=0
        fi
    fi

    # Recreate fonts.list since something changed
    if [[ "${retval}" == 0 ]] ; then
        echo "${fontfiles}" > "${dir}"/fonts.list
    fi

    return ${retval}
}

get_fontdirs() {
    local d
    if [[ $system == 1 ]] ; then
        if [[ $osxfonts == 1 ]] ; then
            find {/System/,/}Library/Fonts -type d
        fi
    else 
        if [[ $osxfonts == 1 && -d "${HOME}/Library/Fonts" ]] ; then
            find "${HOME}/Library/Fonts" -type d
        fi

        if [[ -d "${HOME}/.fonts" ]] ; then
            find "${HOME}/.fonts" -type d
        fi
    fi
}

setup_fontdirs() {
    local x=""
    local fontdirs=""
    local changed="no"

    umask 022

    if [[ $system == 1 ]] ; then
        echo "font_cache: Scanning system font directories to generate X11 font caches"
    else
        echo "font_cache: Scanning user font directories to generate X11 font caches"
    fi

    OIFS=$IFS
    IFS='
'
    for x in $(get_fontdirs) ; do
        if [[ -d "${x}" ]] && check_dirty "${x}" ; then
            if [[ -z "${fontdirs}" ]] ; then
                fontdirs="${x}"
            else
                fontdirs="${fontdirs}${IFS}${x}"
            fi
        fi
    done

    if [[ -n "${fontdirs}" ]] ; then
        echo "font_cache: Making fonts.dir for updated directories."
        for x in ${fontdirs} ; do
            if [[ $verbose == 1 ]] ; then
                echo "font_cache:    ${x}"
            fi

            # First, generate fonts.scale for scaleable fonts that might be there
            @MKFONTSCALE@ \
                -a $ENCODINGSDIR/encodings.dir \
                -a $ENCODINGSDIR/large/encodings.dir \
                -- ${x}

            # Next, generate fonts.dir
            if [[ $verbose == 1 ]] ; then
                @MKFONTDIR@ \
                    -e $ENCODINGSDIR \
                    -e $ENCODINGSDIR/large \
                    -- ${x}
            else
                @MKFONTDIR@ \
                    -e $ENCODINGSDIR \
                    -e $ENCODINGSDIR/large \
                    -- ${x} > /dev/null
            fi
        done
    fi
    IFS=$OIFS

    # Finally, update fontconfig's cache
    echo "font_cache: Updating FC cache"
    if [[ $system == 1 ]] ; then
        @FC_CACHE@ -s \
            $([[ $force == 1 ]] && echo "-f -r") \
            $([[ $verbose == 1 ]] && echo "-v")
    else
        @FC_CACHE@ \
            $([[ $force == 1 ]] && echo "-f -r") \
            $([[ $verbose == 1 ]] && echo "-v")
    fi
    echo "font_cache: Done"
}

do_usage() {
    echo "font_cache [options]"
    echo "    -f, --force        : Force cache recreation"
    echo "    -n, --no-osxfonts  : Just cache X11 font directories"
    echo "                         (-n just pertains to XFont cache, not fontconfig)"
    echo "    -s, --system       : Cache system font dirs instead of user dirs"
    echo "    -v, --verbose      : Verbose Output"
}

cleanup() {
    [[ -r "${FC_LOCKFILE}" ]] && rm -f "${FC_LOCKFILE}"
    exit 1
}

while [[ $# -gt 0 ]] ; do
    case $1 in
        -s|--system) system=1 ;;
        -f|--force) force=1 ;;
        -v|--verbose) verbose=1 ;;
        -n|--no-osxfonts) osxfonts=0 ;;
        --help) do_usage ; exit 0 ;;
        *) do_usage ; exit 1 ;;
    esac
    shift
done

if [[ $system == 1 ]] ; then
    FC_LOCKFILE="/tmp/font_cache.$UID.lock"
elif [[ -w "${TMPDIR}" ]] ; then
    FC_LOCKFILE="${TMPDIR}/font_cache.lock"
elif [[ -w "/tmp" ]] ; then
    FC_LOCKFILE="/tmp/font_cache.$UID.lock"
else
    FC_LOCKFILE="${HOME}/.font_cache.lock"
fi

if [[ -x /usr/bin/lockfile ]] ; then
    if /usr/bin/lockfile -r 0 -l 240 -s 4 -! "${FC_LOCKFILE}" ; then
            echo "font_cache is already running." >&2
            echo "If you believe this to be erroneous, please remove ${FC_LOCKFILE}." >&2
            exit 1
    fi
else
    if [[ -r "${FC_LOCKFILE}" ]] ; then
        read OLD_PID < "${FC_LOCKFILE}"
        if kill -0 ${OLD_PID} >& /dev/null ; then
            echo "font_cache is already running with PID ${OLD_PID}." >&2
            echo "If you believe this to be erroneous, please remove ${FC_LOCKFILE}." >&2
            exit 1
        fi

        echo "Removing stale ${FC_LOCKFILE}" >&2
        rm -f "${FC_LOCKFILE}"
    fi

    echo $$ > "${FC_LOCKFILE}"

    if [[ ! -r "${FC_LOCKFILE}" ]] ; then
        echo "Unable to write to ${FC_LOCKFILE}." >&2
        exit 1
    fi

    # Now make sure we didn't collide mid-air
    read OLD_PID < "${FC_LOCKFILE}"
    if [[ $$ != ${OLD_PID} ]] ; then
        echo "font_cache is already running with PID ${OLD_PID}." >&2
        exit 1
    fi
fi

trap cleanup SIGINT SIGQUIT SIGABRT SIGTERM

setup_fontdirs

rm -f "${FC_LOCKFILE}"