#!/bin/sh

alterator_api_version=1

. alterator-sh-functions
. shell-config
. shell-regexp

url_re='^\(ftp://\|http://\|rsync://\|file:/\)[a-zA-Z0-9._/:@-]\+$'

repo_dir=/etc/apt/repositories/

compatlist_file=/etc/apt/repositories/.compatlist
updates_file=/etc/sisyphus-updates/sisyphus-updates.conf
repolist_file=
schedule_file=/etc/cron.d/alterator-updates
updates_cmd="/usr/sbin/sisyphus-updates >/var/log/sisyphus-updates.log 2>&1"

exit_handler()
{
    local rc=$?
    trap - EXIT

    rm -f "$repolist_file"
    exit $rc
}

trap exit_handler EXIT HUP INT QUIT TERM

repolist_file="$(mktemp -t alterator-updates.XXXXXX)"
grep -v '\(^[[:space:]]*#\|^[[:space:]]*$\)' "$compatlist_file" >"$repolist_file"

validate_mirror()
{
    local m_repolist=";$1;"

    while read repo;do
	[ "$m_repolist" = ";;" -o -z "${m_repolist##*;$repo;*}" ] && return 0
    done<"$repolist_file"
    return 1
}

print_mirror()
{
    local id= repolist= name= comment=
    local IFS='	'
    while read id repolist name comment; do
	    id="${id##*/}"
	    id="${id%%.desktop}"
	    if [ "$repolist" = "all" ] || validate_mirror "$repolist"; then
		write_enum_item "$id" "$name ($comment)"
	    fi
    done
}

list_mirror()
{
    find /etc/apt/mirrors -name '*.desktop'|
	xargs alterator-dump-desktop \
	-v lang="$in_language" \
	-v 'out=Filename;X-Repositories;Name;Comment' \
	-v 'def=nofile;all;noname;'|
	print_mirror
    write_enum_item "custom" "`_ "Custom url"`"
}

list_weekday()
{
    write_enum_item "1" "`_ "monday"`"
    write_enum_item "2" "`_ "tuesday"`"
    write_enum_item "3" "`_ "wednesday"`"
    write_enum_item "4" "`_ "thursday"`"
    write_enum_item "5" "`_ "friday"`"
    write_enum_item "6" "`_ "saturday"`"
    write_enum_item "0" "`_ "sunday"`"
}

list_repo()
{
    local m_file="/etc/apt/mirrors/$1.desktop"
    local m_repolist=";;"

    [ "$1" = "custom" ] ||
	m_repolist=";$(shell_config_get "$m_file" X-Repositories);"

    sed "s/.*/$(quote_sed_regexp "$repo_dir")\/&.desktop/" "$repolist_file"|
	xargs alterator-dump-desktop \
		-v lang="$in_language" \
		-v out='Filename;Name' \
		-v def='noname;'|
	while read name label; do
	    name="${name##*/}"
	    name="${name%%.desktop}"

	    [ "$m_repolist" = ";;" -o -z "${m_repolist##*;$name;*}" ] || continue
	    write_enum_item "$name" "$label"
	done
}

read_schedule()
{
    if [ -s "$schedule_file" ] ;then
	while read min hour monthday month weekday rest;do
	    [ -n "${min%\#*}" ] || continue

	    write_string_param "time" "$hour:$min:00"
	    if [ "$monthday" = "*" -a "$month" = "*" -a "$weekday" = "*" ]; then
	        write_string_param "period" "daily"
	    elif [ "$monthday" = "*" -a "$month" = "*" -a "$weekday" != "*" ];then
	        write_string_param "period" "weekly"
	        write_string_param "weekday" "$weekday"
	    elif [ "$monthday" != "*" -a "$month" = "*" -a "$weekday" = "*" ]; then
	        write_string_param "period" "monthly"
	        write_string_param "monthday" "$monthday"
	    else
	        write_string_param "period" "daily"
	    fi
	    return
	done <"$schedule_file"
    else
	write_string_param "time" "02:00:00"
	write_string_param "period" "daily"
    fi
}

write_schedule()
{
    [ "$in_mode" != "none" ] || return

    if [ "$in_period" = "weekly" -a -z "$in_weekday" ]; then
	    write_error "`_ "Day of week should be selected"`"
	    return
    fi

    if [ "$in_period" = "monthly" -a -z "$in_monthday" ];then
	    write_error "`_ "Day of month should be defined"`"
	    return
    fi

    in_time="${in_time%:*}"
    local hour="${in_time%:*}"
    local min="${in_time#*:}"

    local new_schedule_file="$(mktemp "$schedule_file.XXXXXXXXXX")"
    if [ -z "$new_schedule_file" ]; then
	    write_error "`_ "Unable to create temp file"`"
	    return
    fi

    printf "#autogenerated by alterator-updates\n" >"$new_schedule_file"
    case "$in_period" in
	daily)
	    printf '%s %s * * * root %s\n' "$min" "$hour" "$updates_cmd"
	    ;;
	weekly)
	    printf '%s %s * * %s root %s\n' "$min" "$hour" "$in_weekday" "$updates_cmd"
	    ;;
	monthly)
	    printf '%s %s %s * * root %s\n' "$min" "$hour" "$in_monthday" "$updates_cmd"
	    ;;
    esac >>"$new_schedule_file"
    mv -f "$new_schedule_file" "$schedule_file"
}


on_message() {
  case "$in_action" in
    type)
	write_type_item time time
	write_type_item monthday updates-day
	;;
    read)
	local mode="$(shell_config_get "$updates_file" mode)"
	local mirror="$(shell_config_get "$updates_file" mirror)"
	local custom_url="$(shell_config_get "$updates_file" custom_url)"
	local repolist="$(shell_config_get "$updates_file" repolist|tr ' ' ';')"

	repolist="${repolist#\"}"
	repolist="${repolist%\"}"
	[ -n "$mode" ] || mode="none"
	[ -n "$mirror" ] || mirror="alt"

	write_string_param mode "$mode"
	write_string_param mirror "$mirror"
	write_string_param custom_url "$custom_url"
	write_string_param repolist "$repolist"

	read_schedule
	;;
    write)
	if [ "$in_mode" = "internet" -a -z "$in_repolist" ] ;then
	    write_error "`_ "You should define a minimum one repository"`"
	    return
	fi

	if [ "$in_mode" = "internet" -a "$in_mirror" = "custom" ] ;then
	    if [ -z "$in_custom_url" ]; then
		write_error "`_ "You should define custom url"`"
		return
	    elif echo "$in_custom_url"|grep -qvs "$url_re"; then
		write_error "`_ "Invalid or unsupported protocol. Should be http://, ftp://, rsync:// or file:"`"
		return
	    else
		shell_config_set "$updates_file" custom_url "$in_custom_url"
	    fi
	fi

	[ -z "$in_mode" ] ||
	    shell_config_set "$updates_file" mode "$in_mode"
	[ -z "$in_mirror" ] ||
	    shell_config_set "$updates_file" mirror "$in_mirror"
	[ -z "$in_repolist" ] ||
	    shell_config_set "$updates_file" repolist "\"$(echo "$in_repolist"|tr ';' ' ')\""

	write_schedule
	;;
    list)
	case "$in__objects" in
	    avail_mirror) list_mirror;;
	    avail_weekday) list_weekday;;
	    avail_repo) list_repo "$in_mirror";;
	esac
	;;
  esac
}

message_loop
