#!/bin/bash
DCONFDIR="/etc/dconf"
set -e

if [ $# -ne 2 ] && [ $# -ne 3 ]; then
  echo "$0 [profile] input-filename output-name" > /dev/stderr
  exit 1
fi

if [ $# -eq 3 ]; then
    PROFILE="$1"
    shift
fi

INPUT_FILENAME="$1"
OUTPUT_NAME="$2"

if [ -n $PROFILE ] && [ ! -e ${DCONFDIR}/profile/$PROFILE ]; then
  echo "'$PROFILE' is not valid dconf profile" > /dev/stderr
  exit 1
fi

eval `dbus-launch --sh-syntax`

trap 'kill $DBUS_SESSION_BUS_PID' ERR

declare -A ENTRIES
declare -a UNMATCHED_LINES
OLD_IFS="$IFS"
IFS="
"
FILE=( $(cat "$INPUT_FILENAME") )
IFS=$OLD_IFS

for line in "${FILE[@]}"
do
    echo "$line" | egrep -q '^#' && continue
    SCHEMA_PATTERN=$(echo "$line" | awk '{ print $1 }')
    KEY_PATTERN=$(echo "$line" | awk '{ print $2 }' | awk -F= '{print $1}')
    VALUE=$(echo "$line" | awk '{ print $2 }' | awk -F= '{print $2}')
    SCHEMAS=( $(gsettings list-schemas | egrep -x "$SCHEMA_PATTERN"; true ) )

    [ "${#SCHEMAS}" -eq 0 ] && continue;

    NUM_ENTRIES=0
    IS_STRING=0
    IS_BOOL=0
    IS_NUMBER=0
    case "${VALUE:0:1}" in
       '"'|"'")
       IS_STRING=1
       ;;
       t|T|f|F)
       IS_BOOL=1
       ;;
       *)
       IS_NUMBER=1
       ;;
    esac

    for schema in "${SCHEMAS[@]}"
    do
        KEYS=( $(gsettings list-keys "$schema" | egrep -x "$KEY_PATTERN"; true) )

        for key in "${KEYS[@]}"
        do
OLD_IFS="$IFS"
IFS="
"
            KEY_TYPE=( $(gsettings range $schema $key) )
IFS="$OLD_IFS"
            if [ "${KEY_TYPE[0]}" = 'enum' ]; then
                continue;
            fi
            TYPE="${KEY_TYPE[0]#type }"
            case "$TYPE" in
                b)
                    if [ $IS_BOOL -eq 1 ]; then
                        ENTRIES["$schema $key"]="$VALUE"
                        NUM_ENTRIES=$(($NUM_ENTRIES + 1))
                    fi
                ;;
                s|ay)
                    if [ $IS_STRING -eq 1 ]; then
                        ENTRIES["$schema $key"]="$VALUE"
                        NUM_ENTRIES=$(($NUM_ENTRIES + 1))
                    fi
                ;;
                i|u|q|d|t)
                    if [ $IS_NUMBER -eq 1 ]; then
                        ENTRIES["$schema $key"]="$VALUE"
                        NUM_ENTRIES=$(($NUM_ENTRIES + 1))
                    fi
                ;;
                *)
                ;;
            esac
        done
    done

    if [ $NUM_ENTRIES -lt 1 ]; then
        UNMATCHED_LINES[${#UNMATCHED_LINES[@]}]="$line"
    fi
done

OLD_IFS="$IFS"
IFS="
"
ENTRY_KEYS=( $(for entry in "${!ENTRIES[@]}"; do echo "$entry" ; done | sort ) )
IFS="$OLD_IFS"

TMPFILE="$(mktemp)"
TMPLOCKFILE="$(mktemp)"

cat << EOF > $TMPFILE
# This file is auto-generated from a file called '$(basename $INPUT_FILENAME)'.
#
# Please don't modify this file directly. Instead create your own file next
# to it with a higher numbered prefix.
$(if [ "${#UNMATCHED_LINES[@]}" -gt 0 ]; then
    echo "#"
    echo "# Note, the following lines could not be matched to any known"
    echo "# settings:"
    echo "#"
    for line in "${UNMATCHED_LINES[@]}"
    do
        echo "#      $line"
    done
    echo "#"
fi)
$(OLD_SCHEMA=""
for entry in "${ENTRY_KEYS[@]}"
do
    SCHEMA="$(echo $entry | awk '{print $1}')"
    KEY="$(echo $entry | awk '{print $2}')"
    VALUE="${ENTRIES[$entry]}"

    if [ "$OLD_SCHEMA" != "$SCHEMA" ]; then
        echo
        echo "[$(echo $SCHEMA | sed 's@\.@/@g')]"
        OLD_SCHEMA="$SCHEMA"
    fi
    echo "$KEY=$VALUE"
done)

EOF

for entry in "${ENTRY_KEYS[@]}"
do
    SCHEMA="$(echo $entry | awk '{print $1}')"
    KEY="$(echo $entry | awk '{print $2}')"
    echo "/$(echo $SCHEMA | sed 's@\.@/@g')/$KEY" >> $TMPLOCKFILE
done

if [ -n "${PROFILE}" ]; then
    mkdir -p ${DCONFDIR}/db/${PROFILE}.d/locks
    install -m 644 $TMPLOCKFILE ${DCONFDIR}/db/${PROFILE}.d/locks/${OUTPUT_NAME}-locks
    install -m 644 $TMPFILE ${DCONFDIR}/db/${PROFILE}.d/${OUTPUT_NAME}
    rm -f $TMPLOCKFILE $TMPFILE
    dconf update
else
    chmod 644 $TMPLOCKFILE $TMPFILE
    mv $TMPLOCKFILE ${OUTPUT_NAME}-locks
    mv $TMPFILE ${OUTPUT_NAME}
fi

kill $DBUS_SESSION_BUS_PID
