#!/bin/bash

# Copyright (C) 2016 Piotr Dymacz <piotr@dymacz.pl>

# This script generates "fsdata.c" file for uIP 0.9 stack.
# It takes one argument - name of vendor directory,
# which should contains all www files, at least:
# - index.html (with: <input type="file" name="firmware">)
# - 404.html
# - flashing.hmtl
# - fail.html
#
# All other files are optional. If you want to allow also
# ART and/or U-Boot image update, add the following files,
# with appropriate inputs in form:
# - art.html (<input type="file" name="art">)
# - uboot.html (<input type="file" name="uboot">)
#
# HTML, JS and CSS files are compressed before placing them
# inside "fsdata.c"
#
# You SHOULDN'T embed addresses of any external
# files in "flashing.html" file, because web server,
# after receive POST data, returns this page and stops.

# ================
# Global variables
# ================

# Vendor specific directory
# (default: "general")
VENDOR_DIR=${1:-general}

# Temporary files
FILES_CONTENT_TMP="vendors/.files_content"
   FILES_LIST_TMP="vendors/.files_list"

# YUI Compressor path
# (should be in the same dir)
 YUI_PATH=$(ls -t vendors/*.jar 2> /dev/null | tail --lines=1)

# Previous fsdata_file var name
PREV_FSDATA_STRUCT="NULL"

# Files counter
FS_CNT=0

# Change ASCII to bytes, comma separated
# (e.g. "0x01, 0x02, 0x03...")
function ascii_to_bytes() {
	echo -ne "$1" |\
	      od -A n -t x1 |\
	      tr -d '\r\n' |\
	      sed 's/ /0x/;s/ /, 0x/g;s/.\{102\}/&\n/g' >> "$FILES_CONTENT_TMP"
}

# $1 -> file path
function print_data_array() {
	local f_ext="${1##*.}"
	local f_name="${1##*/}"
	local f_name_no_ext="${f_name%\.*}"
	local f_content=""

	# Open variable declaration
	echo -ne "static const char data_${f_name_no_ext}_${f_ext}[] = {\n" \
		 >> "$FILES_CONTENT_TMP"

	# Content
	case $f_ext in
	css|js)
		f_content=$(cat "$1" | tr -d '\r\n\t' |\
				od -A n -t x1 | tr -d '\r\n' |\
				sed 's/ /0x/;s/ /, 0x/g;s/.\{102\}/&\n/g')
		;;
	png)
		f_content=$(od -A n -t x1 < "$1" | tr -d '\r\n' |\
			    sed 's/ /0x/;s/ /, 0x/g;s/.\{102\}/&\n/g')
		;;
	jpg|jpeg)
		f_content=$(od -A n -t x1 < "$1" | tr -d '\r\n' |\
			    sed 's/ /0x/;s/ /, 0x/g;s/.\{102\}/&\n/g')
		;;
	gif)
		f_content=$(od -A n -t x1 < "$1" | tr -d '\r\n' |\
			    sed 's/ /0x/;s/ /, 0x/g;s/.\{102\}/&\n/g')
		;;
	htm|html)
		f_content=$(cat "$1" | tr -d '\t\r\n' |\
			    od -A n -t x1 | tr -d '\r\n' |\
			    sed 's/ /0x/;s/ /, 0x/g;s/.\{102\}/&\n/g')
		;;
	svg)
		f_content=$(cat "$1" | tr -d '\t\r\n' |\
			    od -A n -t x1 | tr -d '\r\n' |\
			    sed 's/ /0x/;s/ /, 0x/g;s/.\{102\}/&\n/g')
		;;
	*)
		echo "ERROR! Unsupported file type: '${f_name}'!"
		exit 1
	esac

	# File content
	echo -ne "/* Page/File content */\n" >> "$FILES_CONTENT_TMP"
	echo -ne "${f_content}" >> "$FILES_CONTENT_TMP"

	# And close declaration
	echo -ne ", 0 };\n\n" >> "$FILES_CONTENT_TMP"
}

# $1 -> file path
function print_data_struct() {
	local f_ext="${1##*.}"
	local f_name="${1##*/}"
	local f_name_no_ext="${f_name%\.*}"

	echo -ne "const struct fsdata_file file_${f_name_no_ext}_${f_ext}[] = {{\n" >> "$FILES_LIST_TMP"
	echo -ne "\t${PREV_FSDATA_STRUCT},\n" >> "$FILES_LIST_TMP"
	echo -ne "\t\"/${f_name_no_ext}.${f_ext}\",\n" >> "$FILES_LIST_TMP"
	echo -ne "\tdata_${f_name_no_ext}_${f_ext},\n" >> "$FILES_LIST_TMP"
	echo -ne "\t(int)sizeof(data_"$f_name_no_ext"_"$f_ext") - 1\n" >> "$FILES_LIST_TMP"
	echo -ne "}};\n\n" >> "$FILES_LIST_TMP"

	PREV_FSDATA_STRUCT="file_${f_name_no_ext}_${f_ext}"
}

main() {
	if [ -d vendors/$VENDOR_DIR ]; then

		# Remove old fsdata.c
		if [ -e fsdata.c ]; then
			rm -f fsdata.c 2> /dev/null
		fi

		# Temporary files
		touch "$FILES_CONTENT_TMP" \
		      "$FILES_LIST_TMP"

		echo -e "#include <stddef.h>" >> "$FILES_LIST_TMP"
		echo -e "#include \"fsdata.h\"" >> "$FILES_LIST_TMP"

		# Loop through all files in vendor dir
		for file in vendors/${VENDOR_DIR}/*; do
			print_data_array  "$file"
			print_data_struct "$file"
			FS_CNT=$((FS_CNT + 1))
		done

		# Add required defines
		echo -e "#define FS_ROOT\t\t${PREV_FSDATA_STRUCT}" >> "$FILES_LIST_TMP"
		echo -e "#define FS_NUMFILES\t${FS_CNT}"  >> "$FILES_LIST_TMP"

		# Generate new fsdata.c
		cat "$FILES_CONTENT_TMP" > fsdata.c
		cat "$FILES_LIST_TMP"   >> fsdata.c

		rm -f "$FILES_CONTENT_TMP" \
		      "$FILES_LIST_TMP" 2> /dev/null
	else
		echo "ERROR! Vendor specific directory (u-boot/httpd/vendors/${VENDOR_DIR}) doesn't exist!"
		exit 1
	fi
}

# =====================
# Execution begins here
# =====================
main
