#!/bin/bash

# Copyright Jean-Philippe Guillemin <jp.guillemin@free.fr>. This program is free software;
# you can redistribute it and/or modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 of the License,
# or (at your option) any later version. Please take a look at http://www.gnu.org/copyleft/gpl.htm

if ! command -v yad >/dev/null 2>&1; then
  echo "yad is required but was not found in PATH." >&2
  exit 1
fi

if [ ! "$DISPLAY" ]; then
  echo "This program requires a running X session." >&2
  exit 1
fi

export PATH="${PATH}:/usr/sbin:/sbin"

if [ "$(id -u)" != "0" ]; then
  yad --center --title "Root only" --text "You need to be root to run $(basename $0)" --button="OK:0"
  exit
fi

hour="$(date +%H)"
min="$(date +%M)"
sec="$(date +%S)"
month="$(date +%m)"
day="$(date +%d)"
year="$(date +%Y)"
zone=$(ls -l /etc/localtime | sed -n 's/^.*->.*zoneinfo\/\(.*\)$/\1/p')

mode="$1"

infoBox() {
  yad --center --title "$1" --text "$2" --button="OK:0" --image="dialog-information" --width=380
}

warnBox() {
  yad --center --title "Warning" --text "$1" --button="OK:0" --image="dialog-warning" --width=420
}

###############################################
# Main menu

promptAction() {
  mode=$(yad --center --width=480 --height=240 \
    --title "System clock configuration" \
    --text "<b>Current clock set to</b> \"$(date) ($zone)\"" \
    --list --no-headers --separator="" \
    --column="icon:IMG" --column="Action" --column="Description" --column="key:HD" \
    "appointment-new" "Set time" "Configure the time manually" "Set time" \
    "office-calendar" "Set date" "Configure the date manually" "Set date" \
    "preferences-system-time" "Set timezone" "Configure the timezone" "Set timezone" \
    "network-transmit-receive" "NTP" "Use the Network Time Protocol" "NTP" \
    --button="Exit:1" --button="Select:0" \
    --print-column=4 2>/dev/null)
  rc=$?
  mode="$(echo "$mode" | tr -d '\n')"
  if [ $rc -ne 0 ] || [ ! "$mode" ]; then
    mode="none"
  fi
}

setNtp(){
  (
  echo "10" ; echo "# Stopping any running ntpd..."
  killall -9 ntpd 1>/dev/null 2>&1
  echo "40" ; echo "# Syncing with pool.ntp.org..."
  ntpdate pool.ntp.org
  rm -f /var/run/ntpd.pid
  echo "70" ; echo "# Starting ntpd..."
  /etc/rc.d/rc.ntpd start
  echo "90" ; echo "# Writing to hardware clock..."
  hwclock --systoh
  echo "100" ; echo "# Done."
  ) | yad --center --title "NTP update in progress" --text "Please wait..." \
    --progress --auto-close --width=400
}

setNtpSilent(){
  killall -9 ntpd 1>/dev/null 2>&1
  ntpdate pool.ntp.org
  rm -f /var/run/ntpd.pid
  /etc/rc.d/rc.ntpd start
  hwclock --systoh
}

setTime(){
  newTime=$(yad --center --title "Clock adjustment" \
    --text "Enter the new time (HH:MM:SS):" \
    --form --field="Time:" "${hour}:${min}:${sec}" \
    --button="Exit:1" --button="Commit:0")
  rc=$?
  [ $rc -ne 0 ] && return

  clock="${newTime%|}"
  hour="$(echo $clock | cut -d ":" -f1)"
  min="$(echo $clock | cut -d ":" -f2)"
  sec="$(echo $clock | cut -d ":" -f3)"

  if [ "${hour}${min}${sec}" ]; then
    date ${month}${day}${hour}${min}${year}.${sec}
    hwclock --systoh &
  fi
}

setDate(){
  newDate=$(yad --center --title "Date adjustment" \
    --calendar --day="$((10#$day))" --month="$((10#$month))" --year="$year" \
    --date-format="%d-%m-%Y" \
    --button="Exit:1" --button="Commit:0")
  rc=$?
  [ $rc -ne 0 ] && return

  day="$(echo $newDate | cut -d "-" -f1)"
  month="$(echo $newDate | cut -d "-" -f2)"
  year="$(echo $newDate | cut -d "-" -f3)"

  if [ "${day}${month}${year}" ]; then
    date ${month}${day}${hour}${min}${year}.${sec}
    hwclock --systoh &
  fi
}

setZone(){
  # Build the timezone list dynamically instead of hardcoding it
  if command -v timedatectl >/dev/null 2>&1; then
    zoneList=$(timedatectl list-timezones 2>/dev/null)
  fi
  if [ ! "$zoneList" ]; then
    zoneList=$(cd /usr/share/zoneinfo 2>/dev/null && find . -type f \
      ! -name "posixrules" ! -name "localtime" ! -path "./right/*" ! -path "./posix/*" \
      | sed -e 's#^\./##' | sort)
  fi

  # Put the currently active zone first so it's on top and pre-selected
  zoneList="$(printf '%s\n' "$zoneList" | grep -vFx "$zone")"
  zoneList="$(printf '%s\n%s' "$zone" "$zoneList")"

  rowArgs=()
  first="TRUE"
  while IFS= read -r tz; do
    [ ! "$tz" ] && continue
    rowArgs+=("$first" "$tz")
    first="FALSE"
  done <<< "$zoneList"

  newZone=$(yad --center --width=500 --height=560 \
    --title "Time zone configuration" \
    --text "Set the timezone from the list below (current: <b>$zone</b>):" \
    --list --no-headers --radiolist \
    --column="Select" --column="Timezone" \
    --button="Exit:1" --button="Select:0" \
    --print-column=2 \
    "${rowArgs[@]}")
  rc=$?
  newZone="${newZone%|}"
  [ $rc -ne 0 ] && return

  cd /etc
  if [[ "$newZone" && -r /usr/share/zoneinfo/$newZone ]]; then
    ln -sf /usr/share/zoneinfo/$newZone localtime
    zone="$newZone"
  fi
}

[ ! "$mode" ] && promptAction

case $mode in
  "Set time")
    setTime
    exec $0
    ;;
  "Set date")
    setDate
    exec $0
    ;;
  "Set timezone")
    setZone
    exec $0
    ;;
  "NTP")
    setNtp
    exec $0
    ;;
  --ntp)
    setNtpSilent &
    exit
    ;;
  none)
    exit
esac

# end
