#!/bin/sh

openntpd_file=/etc/ntpd.conf
ntp_file=/etc/ntp.conf
chrony_file=/etc/chrony.conf

sysconfigclock_file=/etc/sysconfig/clock
zonetab_file=/usr/share/zoneinfo/zone1970.tab
zoneinfo_dir=/usr/share/zoneinfo

adjtime_file=/etc/adjtime

GCF=/etc/sysconfig/grub2
clocksource_current_file=/sys/devices/system/clocksource/clocksource0/current_clocksource
clocksource_available_file=/sys/devices/system/clocksource/clocksource0/available_clocksource

. alterator-sh-functions
. alterator-service-functions
. shell-config
. shell-var

### ntp

is_ntp_installed()
{
	if [ -f "$chrony_file" ] || [ -f "$openntpd_file" ] || [ -f "$ntp_file" ]; then
		return 0
	else
		return 1
	fi
}

ntpd_rdelim='[[:space:]]\+'
ntpd_wdelim=' '

read_pool()
{
    if [ -f "$chrony_file" ];then
	shell_config_get "$chrony_file" "pool" "$ntpd_rdelim" | cut -f 1 -d"$ntpd_wdelim"  | head -n1
    elif [ -f "$openntpd_file" ];then
	shell_config_get "$openntpd_file" "servers" "$ntpd_rdelim" | head -n1
    elif [ -f "$ntp_file" ];then
	local v="$(shell_config_get "$ntp_file" "server" "$ntpd_rdelim"|head -n1)"
	v="${v%% *}"
	[ "$v" = "127.127.1.0" ] || echo "$v"
    fi
}

write_pool()
{
    if [ -f "$chrony_file" ];then
	shell_config_del "$chrony_file" "pool" "$ntpd_rdelim"
	[ -z "$1" ] || shell_config_set "$chrony_file" "pool" "$1 iburst" "$ntpd_rdelim" "$ntpd_wdelim"
    elif [ -f "$openntpd_file" ];then
	shell_config_del "$openntpd_file" "server" "$ntpd_rdelim"
	shell_config_del "$openntpd_file" "servers" "$ntpd_rdelim"
	[ -z "$1" ] || shell_config_set "$openntpd_file" "servers" "$1" "$ntpd_rdelim" "$ntpd_wdelim"
    elif [ -f "$ntp_file" ];then
    cat>"$ntp_file"<<EOF
#generated by alterator-datetime

driftfile /etc/ntp/drift

$([ -z "$1" ] || printf "server %s iburst burst prefer\n" "$1")
server 127.127.1.0 iburst
fudge  127.127.1.0 stratum 10

restrict default noquery nomodify
restrict 127.0.0.1
EOF
    fi
    if [ -f "$chrony_file" ]; then
	service_control chronyd condrestart
    else
        service_control ntpd condrestart
    fi
}

test_ntp_status()
{
    if [ -f "$chrony_file" ]; then
	service_control chronyd is-enabled
    else
        service_control ntpd is-enabled
    fi
}

write_ntp_status()
{
    if test_bool "$1"; then
      if [ -f "$chrony_file" ]; then

        service_control chronyd on
        service_control chronyd start
      else
	service_control ntpd on
	service_control ntpd start
      fi
    else
      if [ -f "$chrony_file" ]; then
        service_control chronyd off
        service_control chronyd condstop
      else
        service_control ntpd off
        service_control ntpd condstop
      fi
    fi
}

test_ntp_accept()
{
    local result=
    if [ -f "$chrony_file" ]; then
      if result="$(/usr/sbin/control chrony 2>/dev/null)";then
	[ "$result" = "server" ]
      else
	true
      fi
    else
      if result="$(/usr/sbin/control ntpd 2>/dev/null)";then
	[ "$result" = "server" ]
      else
	true
      fi

    fi
}

write_ntp_accept()
{
    if [ -f "$chrony_file" ]; then
      if /usr/sbin/control chrony >/dev/null 2>/dev/null;then
	if test_bool "$1";then
	    /usr/sbin/control chrony server >/dev/null 2>/dev/null
	else
	    /usr/sbin/control chrony client >/dev/null 2>/dev/null
	fi
      else
	true
      fi
    else
      if /usr/sbin/control ntpd >/dev/null 2>/dev/null;then
	if test_bool "$1";then
	    /usr/sbin/control ntpd server >/dev/null 2>/dev/null
	else
	    /usr/sbin/control ntpd client >/dev/null 2>/dev/null
	fi
      else
	true
      fi
    fi
}

### timezone
is_valid_timezone()
{
	local tz="${1-}"

	if [ -n "$tz" ] && [ -f "$zoneinfo_dir/$tz" ]; then
		return 0
	fi

	return 1
}

cat_isotab_file()
{
    local domain="${2:-$po_domain}"
    local langlist="$(write_language "$in_language")"
    local firstlang="${langlist%%:*}"

    LC_ALL="$firstlang" LANGUAGE="$langlist" dumpisotab 2>/dev/null|
	LC_ALL="$firstlang" LANGUAGE="$langlist" sort -k2,2 2>/dev/null
}

# Get timezone from kernel command line.
get_timezone_cmdline()
{
	sed -r -n 's/^(.+[[[:space:]])?tz=([^ ]*).*/\2/p' /proc/cmdline 2>/dev/null
}

GEOIP_URL="https://geoip.altlinux.org"

# Get timezone from geoip server (if network is up).
get_timezone_geoip()
{
	if ip route | grep -qs '^default'; then
		local insecure=

		# Don't use TLS if ca-certificates not installed
		[ -f /usr/share/ca-certificates/ca-bundle.crt ] ||
			insecure="-k"

		curl -s $insecure --max-time 2 "$GEOIP_URL/csv/" | cut -f8 -d,
	fi
}

# Guess timezone based on language.
get_timezone_lang()
{
	local lang="${1-}"
	local region=

	if [ -z "$lang" ]; then
		lang="$(sed -r -n 's/^(.+[[[:space:]])?lang=([^ ]*).*/\2/p' /proc/cmdline 2>/dev/null)"
	fi

	region="$(printf %s "$lang" |
		sed -r -e 's,[a-z]+_([^\.]+)(\..*)?,\1,' |
		tr '[:lower:]' '[:upper:]')"

	[ -z "$region" ] ||
		grep "^$region[[:space:]]" "/etc/alterator/datetime/defaultzones" |cut -f2
}

get_timezone()
{
	local lang="${1-}"
	local tz=

	# First try kernel command line
	tz="$(get_timezone_cmdline)"
	if is_valid_timezone "$tz"; then
		echo "$tz"
		return 0
	fi

	# Second try to use geoip server
	tz="$(get_timezone_geoip)"
	if is_valid_timezone "$tz"; then
		echo "$tz"
		return 0
	fi

	# As last resort try to guess based on language
	tz="$(get_timezone_lang "$lang")"
	if is_valid_timezone "$tz"; then
		echo "$tz"
		return 0
	fi

	return 1
}

read_zone()
{
	local ZONE=
	local language="${1:-$in_language}"

	ZONE="$(shell_config_get "$sysconfigclock_file" "ZONE")"
	shell_var_unquote ZONE "$ZONE"

	if [ -z "$ZONE" ]; then
		ZONE="$(get_timezone "${language%%;*}")"
		[ -n "$ZONE" ] ||
			ZONE="Europe/London"
	fi

	printf "%s\n" "$ZONE"
}

write_zone()
{
	local zone="${1:-$in_zone}"

	is_valid_timezone "$zone" || return 1

	shell_config_set "$sysconfigclock_file" "ZONE" "$zone"
	tzupdate
}

init_timezone()
{
	local zone="${1-}"

	# Check config.
	# We need to setup it if there is no ZONE.
	[ -z "$(shell_config_get "$sysconfigclock_file" "ZONE")" ] ||
		return 0

	if [ -z "$zone" ]; then
		zone="$(read_zone)"
		[ -n "$zone" ] || return 1
	fi

	write_zone "$zone"
}

read_country()
{
    cut -f1,3 "$zonetab_file" |grep "[[:space:]]$1" |cut -f1 |cut -f1 -d','
}

translate_zone()
{
    _ "$1" alterator-tzone-tz|tr '_' ' '
}

country_name()
{
    cat_isotab_file|sed -n "s/^$1[[:space:]]\+//p"
}

list_zone() {
	local IFS="	"
	local code coordinates zone comments
	local tr_zone= tz_num=

	egrep "^([[:upper:]][[:upper:]],)*$1(,[[:upper:]][[:upper:]])*[[:space:]]" "$zonetab_file" |
	while read code coordinates zone comments; do
		tz_num="$(TZ="$zone" date +%:::z)"
		tr_zone="$(translate_zone "$zone")"
		write_enum_item "$zone" "${tr_zone#*/} ($tz_num)"
	done
}

list_country() {
    cat_isotab_file|write_enum
}

### utc

read_utc()
{
    shell_config_get "$sysconfigclock_file" UTC
}

write_utc()
{
    if test_bool "$1";then
	shell_config_set "$sysconfigclock_file" UTC "true"
    else
	shell_config_set "$sysconfigclock_file" UTC "false"
    fi
}

### /etc/adjtime

is_adjtime_utc()
{
    [ -s "$adjtime_file" ] || return 0

    if [ "$(sed -n '3p' "$adjtime_file")" = "LOCAL" ]; then
        return 1
    else
        return 0
    fi
}

set_adjtime_utc()
{
    local new_str= old_str=

    if test_bool "$1"; then
        new_str=UTC
        old_str=LOCAL
    else
        new_str=LOCAL
        old_str=UTC
    fi

    if [ -s "$adjtime_file" ]; then
        sed -i "3{s/$old_str/$new_str/}" "$adjtime_file"
    else
        cat > "$adjtime_file" <<EOF
0.0 0 0
0
$new_str
EOF
    fi
}

### clocksource

clocksource_edit_grub() {
    [ -n "$1" ] || return

    if grep -q -e "^GRUB_CMDLINE_LINUX_DEFAULT=.*clocksource.*" "$GCF"
    then
        sed -i -e "/^GRUB_CMDLINE_LINUX_DEFAULT=/s/clocksource=[a-zA-Z0-9_-]*/clocksource=$1/" "$GCF"
    else
        sed -i -e "/^GRUB_CMDLINE_LINUX_DEFAULT=/s/'/ clocksource=$1'/2" "$GCF"
    fi

    update-grub &>/dev/null
}

clocksource_set() {
    [ -n "$1" ] || return

    [ "$1" != $(clocksource_current) ] || return

    echo "$1" > "$clocksource_current_file"
    clocksource_edit_grub "$1"
}

clocksource_current() {
    cat "$clocksource_current_file"
}

clocksource_available() {
    cat "$clocksource_available_file" | tr " " "\n" | write_enum
}

clocksource_show() {
    [ $(arch) == "x86_64" ] && echo "Yes" || echo "No"
}
