#!/bin/sh -e
#
# https://www.dioptre.fr/bin/brg
# Copyright 2020 Damien Riou <contact@dioptre.fr>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#

main() {
        test -n "$1" || usage
 	test -d "$1" || no_dir "$1"
 	test -f "$1/_brg.md" || no_file "$1"
        test -n "$2" || usage

        src="$1"
        base_url="${2%/}"
        test -n "$3" && blog_url="${3%/}" || blog_url="$base_url"
        blog_path="$(echo "$blog_url" | sed 's|'"$base_url"'||')"

        files=$(blog_posts_list)
        first_year=$(first_publication_year)
        current_year=$(date +'%Y')

        render_index_header
        render_feed_header
        year=$first_year
        for year in $(seq "$current_year" -1 "$first_year")
        do
                files_year=$(blog_posts_list_year)
                test -z "$files_year" && continue
                (render_h2_year)
                treated_posts=$(render_posts_list_year)
        done
        render_feed_footer

        echo "$treated_posts" | tac >&2
	printf '[brg] ' >&2
	print_status 'post' 'posts' "$treated_posts" >&2
        echo >&2
}

usage() {
        echo "usage: ${0##*/} src base_url blog_url" >&2
	exit 1
}

no_dir() {
	echo "${0##*/}: $1: No such directory" >&2
	exit 2
}

no_file() {
	echo "${0##*/}: No _brg.md file detected" >&2
	exit 3
}

print_status() {
	test -z "$3" && printf 'no %s' "$2" && return

	echo "$3" | awk -v singular="$1" -v plural="$2" '
	END {
		if (NR==1) printf NR " " singular
		if (NR>1) printf NR " " plural
	}'
}

blog_posts_list() {
        cd "$src"
        find . -type f -a \( -name "*.md" -o -name "*.html" \) | sort -V |
                grep -E "^./[0-9]{4}-[0-9]+-\S+"
}

blog_posts_list_year() {
        echo "$files" | grep -E '^./'"$year"'-' | tac
}

first_publication_year() {
        echo "$files" | grep -oE '[0-9]{4}' | head -1
}

render_index_header() {
        cp "$src"/_brg.md "$src"/index.md >&2
}

render_h2_year() {
        echo "$year" | sed '1s/^/\n## /' >> "$src"/index.md
}

render_posts_list_year() {
        cd "$src"
        for post_name in $files_year
        do
                test "${post_name##*.}" = "md" && render_post_item_md
                test "${post_name##*.}" = "html" && render_post_item_html
                treated_posts="$(printf "%s\n$treated_posts" "$post_name")"
        done
        echo "$treated_posts"
}

render_post_item_md() {
        post_title="$(get_post_title_md)"
        post_address_html="$(echo "$post_name" | sed 's|^\.|'"$blog_path"'|;s|.md$|.html|')"
        post_date_expression="$(get_post_date_md)"
        render_post_item
        post_description=$(Markdown.pl "$post_name" | rel_to_abs_urls | remove_nbsp)
        post_guid="$(echo "$post_name" | sed 's|^\.|'"$blog_url"'|;s|.md$|.html|')"
        render_feed_item
}

get_post_date_md() {
        grep '^\[date\]: <>' "$post_name" | sed 's/.*(\(.*\))/\1/'
}

get_post_title_md() {
        grep '^\[title\]: <>' "$post_name" | sed 's/.*(\(.*\))/\1/'
}

render_post_item_html() {
        post_title="$(get_post_title_html)"
        post_address_html="$(echo "$post_name" | sed 's|^\.|'"$blog_path"'|')"
        post_date_expression="$(get_post_date_html)"
        render_post_item
        post_description=$(< "$post_name" rel_to_abs_urls | remove_nbsp)
        post_guid="$(echo "$post_name" | sed 's|^\.|'"$blog_url"'|')"
        render_feed_item
}

get_post_date_html() {
        grep '^<\!\-\-date: ' "$post_name" | grep -oE "[0-9]{4}-[0-9]{2}-[0-9]{2}"
}

get_post_title_html() {
        grep '^<h1' "$post_name" | sed 's/.*<h1.*>\(.*\)<\/h1>.*/\1/'
}

get_post_date_human() {
        date --date="$post_date_expression" +'%-d %B %Y' | tr '[:upper:]' '[:lower:]'
}

render_post_item() {
        post_date="$(get_post_date_human)"
        post_title_link="[$post_title]($post_address_html)"
        post_entry="+ $post_date - $post_title_link"
        echo "$post_entry" >> index.md
}

render_feed_header() {
        feed_url="$blog_url/rss.xml"
        feed_title=$(get_feed_title)
        feed_description=$(get_feed_description)
	echo '<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<atom:link href="'"$feed_url"'" rel="self" type="application/rss+xml" />
<title>'"$feed_title"'</title>
<description>'"$feed_description"'</description>
<link>'"$blog_url"'/</link>
<lastBuildDate>'"$(date_rfc_822 "$(date -I)")"'</lastBuildDate>
' > "$src"/rss.xml
}

render_feed_item() {
        echo '<item>
<guid>'"$post_guid"'</guid>
<link>'"$post_guid"'</link>
<pubDate>'"$(date_rfc_822 "$post_date_expression")"'</pubDate>
<title>'"$post_title"'</title>
<description><![CDATA[
'"$post_description"'
]]></description>
</item>
' >> rss.xml
}

render_feed_footer() {
        echo '</channel>
</rss>' >> "$src"/rss.xml
}

get_feed_title() {
        grep -E '^#[^#]' "$src"/_brg.md | sed 's/^# *\(.*\)/\1/'
}

get_feed_description() {
        sed '/^$/d' "$src"/_brg.md | head -2 | tail -1
}

remove_nbsp() {
	sed 's#\&nbsp;# #g'
}

rel_to_abs_urls() {
	abs='s#(src|href)="/([^"]*)"#\1="'"$base_url"/'\2"#g'
	rel='s#(src|href)="([^:/"]*)"#\1="'"$blog_url"/'\2"#g'
	sed -E "$abs;$rel"
}

date_rfc_822() {
        LANG=C date -d "$1" '+%a, %d %b %Y %H:%M:%S %z'
}

main "$@"
