#!/bin/bash -eu

# MIT License
#
# Copyright (c) 2017 Grigory Ustinov <grenka@altlinux.org>
# Copyright (c) 2017 Ivan Zakharyaschev <imz@altlinux.org>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

# these paths cant vary and common for next functions
schemaspath="/usr/share/glib-2.0/schemas/"
profileuser="/etc/dconf/profile/user"

processfile()
{
    local -r schemasname="$1"; shift #[ name of *.gschema.xml file ]
    IFS=' ' # Internal Field Separator
    if [ "$schemasname" != ca.desrt.dconf-editor ]; then # this is bad file
        local -r currentschema="$schemaspath$schemasname.gschema.xml"
        local -r settings="/etc/dconf/db/local.d/$schemasname"
        local -r settingslocks="/etc/dconf/db/local.d/locks/$schemasname"
        # create output files
        echo -n "" > "$settings"
        echo -n "" > "$settingslocks"

        if [ -f "$currentschema" ]; then # for case of simple .xml files
            local path
            local -a names values
            local valueJ
            for path in $(xmllint --xpath '//schemalist/schema/@path' "$currentschema" 2>/dev/null | \
                    sed -n 's/path="\/\|"//gp'); do
                echo "Processing: [${path%?}]"
                echo "[${path%?}]" >> "$settings"

                names=($(xmllint --xpath "//schemalist/schema[@path=\"/$path\"]/key/@name" "$currentschema" 2>/dev/null | \
                    sed -n 's/name="\|"/ /gp'))
                # remove [ lists ] by replacing them on ~
                # substitute ? instead of spaces for correct transfer of 'strings with spaces'
                values=($(xmllint --nocdata --xpath "//schemalist/schema[@path=\"/$path\"]/key/default" "$currentschema" 2>/dev/null | \
                    sed -n 's/\[[^<]*\]/~/g; s/ /\?/g; s/<default[^>]*>\|<\/default>/ /gp'))

                for (( j=0; j < ${#values[*]}; j++ )); do
                    if [ "${values[$j]}" != "~" ] && \
                       [ "${values[$j]}" != "nothing" ]; then # dconf doesnt know this value
                        valueJ=$(sed -n 's/\?/ /g; p' <<< "${values[$j]}" )
                        echo "${names[$j]}=$valueJ" >> "$settings"
                        echo "/$path${names[$j]}" >> "$settingslocks"
                    fi
                done
            done
        fi
    fi
}
# end processfile --- --- --- --- ---

lock()
{
    local -r typeoflock="$1"; shift
    # anyway create this
    mkdir -p "/etc/dconf/db/local.d/locks"
    echo -e "user-db:user\nsystem-db:local" > "$profileuser"

    local file filename arg
    if [ "$typeoflock" == "all" ]; then
        for file in "$schemaspath"/* ; do
            filename=${file##*/}
            processfile "${filename%.gschema.xml}"
        done
    elif [ "$typeoflock" == "list" ]; then
        for arg in "$@"; do
             processfile "${arg%.gschema.xml}"
        done
    else
        echo "Error: Undefined error, that never should happen!"
        exit 3
    fi

    dconf update
    echo "Dconf locked successfully!"
}
# end lock --- --- --- --- ---

unlock()
{
    local -r typeoflock="$1"; shift

    local -r basepath="/etc/dconf/db/local.d"
    local -r lockspath="$basepath/locks"

    local file arg
    if [ "$typeoflock" == "all" ]; then
        for file in "$basepath"/* ; do
            rm -f "$lockspath/${file##*/}" # that's really enough, all other files will be cleaned in Total clean section
        done
    elif [ "$typeoflock" == "list" ]; then
        for arg in "$@"; do
            rm -f "$basepath/${arg%.gschema.xml}" "$lockspath/${arg%.gschema.xml}"
        done
    else
        echo "Error: Undefined error, that never should happen!"
        exit 3
    fi

    # Total clean
    if [ $(ls "$lockspath" | wc -l) = "0" ]; then
        rm -f "$profileuser" "/etc/dconf/db/local"
        rm -rf "$basepath"
    fi

    dconf update
    echo "Dconf unlocked!"
}
# end unlock --- --- --- --- ---
