#!/bin/sh

alterator_api_version=1

po_domain="alterator-pkg"
repository_dir=/etc/apt/repositories
sourcelist="/etc/apt/sources.list /etc/apt/sources.list.d/*"

uri_re='^\(ftp://\|http://\|rsync://\|file:/\)[a-zA-Z0-9._/:@-]\+$'
prefix_re="[[:space:]]*rpm[[:space:]]\+\([^[:space:]]\+[[:space:]]\+\)\?"
base_re="$prefix_re\([^[:space:]]\+\)"
all_re="^#\?$base_re"

rpm_arch="$(rpm --eval '%_host_cpu')"

. alterator-sh-functions
. shell-quote

### special hackaround for backward compatibility
make_pattern()
{
    local r_path="$1";shift
    local r_noarch="$1";shift
    local r_comps="$1";shift

    printf '%s%%20%s%%20%s' "$r_path" "$rpm_arch" "$r_comps"
    [ "$r_noarch" = "no" ] ||
	printf ';%s%%20noarch%%20%s' "$r_path" "$r_comps"
}

### desktop-like files
desktop_awk()
{
    alterator-dump-desktop \
        -v lang="$in_language" \
        -v out="X-Path;X-Has-Noarch;X-Components;Name" \
        -v def="/notfound;no;classic;" \
	"$@"
}

desktop_list()
{
    find $repository_dir -name '*.desktop'
}


### uri work

decode_uri()
{
    echo "$1"|
	sed \
	    -e 's,%20, ,g'
}

has_uri()
{
    local pattern="$pattern";shift

    local OLD_IFS="$IFS"
    local IFS=";"

    for i in $pattern; do
	    IFS="$OLD_IFS"
	    local postfix="$(decode_uri "$i")"
	    grep -qs "$all_re$(quote_sed_regexp "$postfix")\$" $sourcelist || return 1
    done
    return 0
}

has_uri1()
{
    local pattern="$1";shift
    local new_uri="$1";shift
    local postfix="$(decode_uri "${pattern##*;}")"

    postfix="$(quote_sed_regexp "$postfix")"
    new_uri="$(quote_sed_regexp "$new_uri")"

    grep -qs "^#\?$prefix_re$new_uri$postfix\$" $sourcelist
}

add_uri()
{
    local pattern="$1";shift
    local new_uri="$1";shift

    [ -n "${new_uri##/*}" ] || new_uri="file:$new_uri"

    if echo "$new_uri"|grep -qvs "$uri_re"; then
	write_error "`_ "Invalid or unsupported protocol. Should be http://, ftp://, rsync:// or file:"`"
	return 1
    elif has_uri1 "$pattern" "$new_uri"; then
	write_error "`_ "Same source already exists"`"
	return 1
    fi

    local IFS=";"
    for i in $pattern; do
	local postfix="$(decode_uri "$i")"
	printf '#rpm %s%s\n' "$new_uri" "$postfix" >>/etc/apt/sources.list
    done

    return 0
}

delete_uri()
{
    local pattern="$1";shift
    local uri="$(quote_sed_regexp "$1")";shift

    local OLD_IFS="$IFS"
    local IFS=";"

    for i in $pattern; do
	    IFS="$OLD_IFS"
	    local postfix="$(decode_uri "$i")"
	    postfix="$(quote_sed_regexp "$postfix")"

	    sed "/^#\?$prefix_re$uri$postfix\$/ d" -i $sourcelist
    done
}

off_uri()
{
    local pattern="$1";shift

    local OLD_IFS="$IFS"
    local IFS=";"

    for i in $pattern; do
	    IFS="$OLD_IFS"
	    local postfix="$(decode_uri "$i")"
	    postfix="$(quote_sed_regexp "$postfix")"
	    sed "s/^$base_re$postfix\$/#rpm \1\2$postfix/" -i $sourcelist
    done
}

on_uri()
{
    local pattern="$1";shift
    local new_uri="$1";shift
    new_uri="$(quote_sed_regexp "$new_uri")"

    local OLD_IFS="$IFS"
    local IFS=";"

    for i in $pattern; do
	    IFS="$OLD_IFS"
	    local postfix="$(decode_uri "$i")"
	    postfix="$(quote_sed_regexp "$postfix")"
	    sed "s/^#$prefix_re$new_uri$postfix\$/rpm \1$new_uri$postfix/" -i $sourcelist
    done
}

read_uri()
{
    local pattern="$1";shift
    local postfix="$(decode_uri ${pattern##*;})" #use only one pattern
    local v="$(sed -n "s/^$base_re$(quote_sed_regexp "$postfix")\$/\2/p" $sourcelist|head -n1)" #"

    [ -n "$v" ] || v="inactive"
    echo "$v"
}

list_uri()
{
    local pattern="$1";shift
    local postfix="$(decode_uri ${pattern##*;})" #use only one pattern

    sed -n "s/$all_re$(quote_sed_regexp "$postfix")\$/\2/p" $sourcelist
}

### list/read


write_repository_item()
{
    local name="$1";shift
    local label="$1";shift
    local pattern="$1";shift

    has_uri "$pattern" || return

    local uri="$(read_uri "$pattern")"

    [ "$uri" != "inactive" ] || uri="`_ "inactive"`"

    write_enum_item "$name" "$label ($uri)"
}

list_repository()
{
    desktop_list|
	while read i; do
	local name="${i%%.desktop}"
	desktop_awk "$i"|
	    (read r_path r_noarch r_comps description;
		pattern="$(make_pattern "$r_path" "$r_noarch" "$r_comps")"
		write_repository_item "${name##*/}" "$description" "$pattern")
    done
}


list_mirror()
{

    [ -f "$repository_dir/$1.desktop" ] || return 0

    write_enum_item "inactive" "`_ "inactive"`"
    desktop_awk "$repository_dir/$1.desktop"|
	(read r_path r_noarch r_comps description;
	    pattern="$(make_pattern "$r_path" "$r_noarch" "$r_comps")"
	    list_uri "$pattern"|write_enum)
}

read_mirror()
{
    [ -f "$repository_dir/$1.desktop" ] || return 0

    desktop_awk "$repository_dir/$1.desktop"|
	(read r_path r_noarch r_comps description;
	    pattern="$(make_pattern "$r_path" "$r_noarch" "$r_comps")"
	    write_string_param label "$description"
	    write_string_param uri "$(read_uri "$pattern")")
}

write_mirror()
{
    local name="$1";shift
    local new_uri="$1";shift

    [ -n "$name" -a -n "$new_uri" ] || return 0
    [ -f "$repository_dir/$name.desktop" ] || return 0

    desktop_awk "$repository_dir/$name.desktop"|
	(read r_path r_noarch r_comps description;
	    pattern="$(make_pattern "$r_path" "$r_noarch" "$r_comps")"
	    off_uri "$pattern"
	    [ "$new_uri" = "inactive" ] || on_uri "$pattern" "$new_uri")
}

new_mirror()
{
    local name="$1";shift
    local new_uri="$1";shift

    [ -n "$name" -a -n "$new_uri" ] || return 0
    [ -f "$repository_dir/$name.desktop" ] || return 0

    desktop_awk "$repository_dir/$name.desktop"|
	(read r_path r_noarch r_comps description;
	    pattern="$(make_pattern "$r_path" "$r_noarch" "$r_comps")"
	    add_uri "$pattern" "$new_uri")
}

delete_mirror()
{
    local name="$1";shift
    local uri="$1";shift

    [ "$uri" != "inactive" ] || return 0

    [ -n "$name" -a -n "$uri" ] || return 0
    [ -f "$repository_dir/$name.desktop" ] || return 0

    desktop_awk "$repository_dir/$name.desktop"|
	(read r_path r_noarch r_comps description;
	    pattern="$(make_pattern "$r_path" "$r_noarch" "$r_comps")"
	    delete_uri "$pattern" "$uri")
}

### normalize sources
sed  \
    -e "s/^\(#\?\)$prefix_re\([^[:space:]]\+\)\/\([[:space:]]\+\)\(noarch\|$rpm_arch\)/\1rpm \2\3\4\5/" \
    -i $sourcelist
sed \
    -e 's/[[:space:]]\+$//' \
    -i $sourcelist

on_message()
{
	case "$in_action" in
		list)
		    case "${in__objects}" in
			avail_repository) list_repository;;
			avail_mirror) [ -z "$in_name" ] || list_mirror "$in_name" ;;
		    esac
		    ;;
		read)
		    [ -z "$in_name" ] || read_mirror "$in_name"
		    ;;
		write)
		    [ -n "$in_name" ] || return
		    if [ -n "$in_new" ]; then
		        new_mirror "$in_name" "$in_new_uri" || return 0
		    elif [ -n "$in_delete" ]; then
		        [ -z "$in_name" ] || delete_mirror "$in_name" "$in_uri"
		    elif [ -n "$in_commit" ]; then
		        write_mirror "$in_name" "$in_uri"
		    fi
		    ;;
	esac
}

message_loop
