#!/usr/bin/env bash

# ----- Parameters ------ #
# Coordinates: https://www.mapcoordinates.net/en
# Set lat and long explicitly, or leave commented to get them automatically from ipinfo.io
lat="${lat:-}"
long="${long:-}"
# Calculation Method: https://api.aladhan.com/v1/methods
method='4'
# Print Text Language (en/ar)
print_lang='en'
# Notifcation Daemon
notify='mako'
# ----------------------- #
prayers_json="${HOME}/.local/share/prayers.json"
prayers=("Fajr" "Dhuhr" "Asr" "Maghrib" "Isha")
declare -A date
declare -A epochtimes
declare -A prayers_ar
prayers_ar=(
  ["Fajr"]="الفجر"
  ["Sunrise"]="الشروق"
  ["Dhuhr"]="الظهر"
  ["Asr"]="العصر"
  ["Maghrib"]="المغرب"
  ["Isha"]="العشاء"
)
date=(
  [day_idx]=$(($(date +%-d) - 1))
  [weekday]=$(date +%a)
  [month]=$(date +%-m)
  [year]=$(date +%Y)
)

nameof() {
  if [[ "${print_lang}" != "en" ]]; then
    local array_name="prayers_${print_lang}"
    eval "echo -n \${${array_name}[${1}]}"
  else
    echo -n "${1}"
  fi
}

check() {
  local available_month
  local response
  local location
  if [[ -r "${prayers_json}" ]]; then
    available_month=$(jq -r ".data[0].date.gregorian.month.number" "${prayers_json}")
  else
    local fetch_prayers=1
  fi

  if ((fetch_prayers)) || [[ "${available_month}" != "${date[month]}" ]]; then
    if [[ -z "${lat}" ]] || [[ -z "${long}" ]]; then
      echo "-- fetching latitude and longitude (from ipinfo.io)"
      response="$(curl -s https://ipinfo.io)"
      # parse city name
      city=$(echo "${response}" | jq -r '.city')
      echo "-- city: ${city}"
      # parse the latitude and longitude
      mapfile -t location < <(echo "${response}" | jq -r ' (.loc | split(","))[] ')
      # set `lat` to `latitude`, or default to the specified value above
      lat=${location[0]:-${lat}}
      long=${location[1]:-${long}}
    fi

    echo "-- latitude: ${lat}, longitude: ${long}"
    echo "-- fetching current month prayer calendar (${date[month]}-${date[year]})"
    # Documentation: https://aladhan.com/prayer-times-api#GetCalendar
    curl -Lso "${prayers_json}" "https://api.aladhan.com/v1/calendar/${date[year]}/${date[month]}?latitude=${lat}&longitude=${long}&method=${method}"
  fi
}

add-jobs() {
  # WARNING: THIS SCRIPTS REMOVES ALL JOBS IN QUEUE "P" SCHEDULED USING AT (ADJUST ACCORDINGLY)
  echo "-- removing all jobs in queue 'p'"
  if [[ "$(at -q p -l | wc -l)" != "0" ]]; then
    for i in $(at -q p -l | awk '{ print $1 }'); do
      atrm "${i}"
    done
  fi

  for prayer in "${prayers[@]}"; do
    echo "-- creating at job for ${prayer} prayer"
    if [[ "${notify}" == "mako" ]]; then
      printf 'notify-send -t 30000 --icon="clock-applet-symbolic" "Prayer Times" "It is time for %s prayer 🕌"' "${prayer}" | at -q p "$(timeof "${prayer}" '%H:%M %F')"
    else
      printf '[ "$(dunstify --icon="clock-applet-symbolic" --action="Reply,reply" "Prayer Times" "Time for %s prayer 🕌" -t 30000)" = "2" ] && %s' "${prayer}" "${HOME}/.local/bin/toggle-athan" | at -q p "$(timeof "${prayer}" '%H:%M %F')"
    fi
  done
}

timeof() {
  [[ "${#}" -lt "1" ]] && echo "atleast 1 argument is needed" && return 1
  echo -n "$(date -d "$(jq -r ".data[${date[day_idx]}].timings.${1}" "${prayers_json}")" "+${2:-%I:%M}")"
}

hijri() {
  case "${1}" in
  weekday)
    if [[ "${print_lang}" == "ar" ]]; then
      echo -n "$(jq -r ".data[${date[day_idx]}].date.hijri.weekday.ar" "${prayers_json}")"
    else
      echo -n "$(jq -r ".data[${date[day_idx]}].date.hijri.weekday.en" "${prayers_json}")"
    fi
    ;;
  day)
    echo -n "$(jq -r ".data[${date[day_idx]}].date.hijri.day" "${prayers_json}")"
    ;;
  month)
    if [[ "${print_lang}" == "ar" ]]; then
      echo -n "$(jq -r ".data[${date[day_idx]}].date.hijri.month.ar" "${prayers_json}")"
    else
      echo -n "$(jq -r ".data[${date[day_idx]}].date.hijri.month.en" "${prayers_json}")"
    fi
    ;;
  year)
    echo -n "$(jq -r ".data[${date[day_idx]}].date.hijri.year" "${prayers_json}")"
    ;;
  *)
    echo "unsupported argument: ${1}" && return 1
    ;;
  esac
}

settimes() {
  # return if array already populated
  [[ "${#epochtimes[@]}" -gt 0 ]] && return 0

  epochtimes=(
    [now]=$(date +%s)
    [fajr]=$(timeof Fajr %s)
    [dhuhr]=$(timeof Dhuhr %s)
    [asr]=$(timeof Asr %s)
    [maghrib]=$(timeof Maghrib %s)
    [isha]=$(timeof Isha %s)
  )

  local nxt_idx=0
  local curr_idx=4
  for i in {4..0}; do
    local prayer_key="${prayers[${i}],,}"
    if [[ "${epochtimes[now]}" -ge "${epochtimes[${prayer_key}]}" ]]; then
      [[ "${i}" -lt "4" ]] && curr_idx=${i} && nxt_idx=$((i + 1))
      break
    fi
  done

  local next_key="${prayers[${nxt_idx}],,}"
  epochtimes[next]="${epochtimes[${next_key}]}"
  currentprayer="${prayers[${curr_idx}]}"
  nextprayer="${prayers[${nxt_idx}]}"
  if [[ "${nxt_idx}" == "1" && "${date[weekday]}" == "Fri" ]]; then
    nextprayer="Jumuaa"
  fi
}

timeto() {
  [[ "${#}" -lt "1" ]] && echo "atleast 1 argument are needed" && return 1
  settimes
  remain="$((epochtimes["${1,,}"] - epochtimes[now]))"
  [[ "${remain}" -lt "0" ]] && remain="$((remain + 86400))"
  date -u -d"@${remain}" "+${2:-%H:%M}"
}

print() {
  local format="📅 %s،%s\n%-12s%-10s\n%-12s%-10s\n%-12s%-10s\n%-12s%-10s\n%-12s%-10s\n%-12s%-10s\n"
  if [[ "${print_lang}" == "ar" ]]; then
    format="📅 %s،%s\n%s%11s\n%s%10s\n%s%11s\n%s%11s\n%s%10s\n%s%10s\n"
  fi

  printf "${format}" \
    "$(hijri weekday)" \
    "$(hijri day)-$(hijri month)-$(hijri year)" \
    "۞ $(nameof Fajr)" "$(timeof Fajr)" \
    "۞ $(nameof Sunrise)" "$(timeof Sunrise)" \
    "۞ $(nameof Dhuhr)" "$(timeof Dhuhr)" \
    "۞ $(nameof Asr)" "$(timeof Asr)" \
    "۞ $(nameof Maghrib)" "$(timeof Maghrib)" \
    "۞ $(nameof Isha)" "$(timeof Isha)"
}

yad-en() {
  yad \
    --text-width=10 \
    --on-top \
    --text \
    "<span font-size='large'><b>📅 $(hijri weekday),$(hijri day)-$(hijri month)-$(hijri year)</b></span>" \
    --list \
    --width=300 \
    --height=250 \
    --title="Prayers" \
    --column="Prayer" \
    --column="Time" \
    --expand-column=1 \
    --no-buttons \
    --no-click \
    --no-selection \
    "<span font-size='large'>$(nameof Fajr)</span>" "<span font-size='large'>$(timeof Fajr)</span>" \
    "<span font-size='large'>$(nameof Sunrise)</span>" "<span font-size='large'>$(timeof Sunrise)</span>" \
    "<span font-size='large'>$(nameof Dhuhr)</span>" "<span font-size='large'>$(timeof Dhuhr)</span>" \
    "<span font-size='large'>$(nameof Asr)</span>" "<span font-size='large'>$(timeof Asr)</span>" \
    "<span font-size='large'>$(nameof Maghrib)</span>" "<span font-size='large'>$(timeof Maghrib)</span>" \
    "<span font-size='large'>$(nameof Isha)</span>" "<span font-size='large'>$(timeof Isha)</span>"
}

yad-ar() {
  yad \
    --text-width=10 \
    --on-top \
    --text-align='right' \
    --text \
    "<span font-size='large'><b>📅 $(hijri weekday),$(hijri day)-$(hijri month)-$(hijri year)</b></span>" \
    --list \
    --width=250 \
    --height=240 \
    --title="Prayers" \
    --column="الوقت" \
    --column="الصلاة" \
    --expand-column=1 \
    --no-buttons \
    --no-click \
    --no-selection \
    "<span font-size='large'>$(timeof Fajr)</span>" "<span font-size='large'>$(nameof Fajr)</span>" \
    "<span font-size='large'>$(timeof Sunrise)</span>" "<span font-size='large'>$(nameof Sunrise)</span>" \
    "<span font-size='large'>$(timeof Dhuhr)</span>" "<span font-size='large'>$(nameof Dhuhr)</span>" \
    "<span font-size='large'>$(timeof Asr)</span>" "<span font-size='large'>$(nameof Asr)</span>" \
    "<span font-size='large'>$(timeof Maghrib)</span>" "<span font-size='large'>$(nameof Maghrib)</span>" \
    "<span font-size='large'>$(timeof Isha)</span>" "<span font-size='large'>$(nameof Isha)</span>"
}

yad-toggle() {
  local yad_pid
  yad_pid=$(pgrep -f 'yad.*Prayers')

  if [[ -z "${yad_pid}" ]]; then
    if [[ "${print_lang}" == "ar" ]]; then
      yad-ar
    else
      yad-en
    fi

  else
    kill "${yad_pid}"
  fi
}

current() {
  settimes
  echo "${currentprayer}"
}

next() {
  settimes
  echo "${nextprayer}"
}

remaining() {
  settimes
  timeto next "%H:%M:%S"
}

status() {
  settimes
  local remain
  remain="$(timeto next)"
  echo "${nextprayer} in ${remain}"
}

waybar-status() {
  settimes
  local remain
  remain="$(timeto next)"
  local next_text="${nextprayer} in ${remain}"
  printf '{ "text": "%s", "class": "%s" }' "${next_text}" "${nextprayer}"
}

case "${1}" in
check)
  check
  ;;
jobs)
  add-jobs
  ;;
sync)
  check
  add-jobs
  ;;
print)
  print
  ;;
current)
  current
  ;;
next)
  next
  ;;
remaining)
  remaining
  ;;
status)
  status
  ;;
yad)
  yad-toggle
  ;;
waybar)
  waybar-status
  ;;
timeto)
  if [[ -n "${2}" ]]; then
    if [[ "${2}" == "next" ]]; then
      valid=1
    else
      for p in "${prayers[@]}"; do
        if [[ "${2^}" == "${p}" ]]; then
          valid=1
          break
        fi
      done
    fi
  fi

  if [[ -z "${valid}" ]]; then
    IFS='|'
    echo "Usage: $(basename "${0}") timeto (next|${prayers[*],,})"
    exit 1
  fi

  timeto "${2}"
  ;;
*)
  echo "Usage: $(basename "${0}") [command]"
  echo "Command:"
  echo "  check      Check if prayer time data needs to be fetched"
  echo "  jobs       Add prayer time notifications as at jobs"
  echo "  sync       Check and sync prayer time data, and add notifications"
  echo "  print      Print prayer times"
  echo "  current    Get the current prayer"
  echo "  next       Get the next prayer"
  echo "  remaining  Get the remaining time for the next prayer"
  echo "  status     Get the status message indicating the next prayer"
  echo "  timeto     Get the time remaining for a prayer"
  echo "  yad        Toggle the yad window showing prayer times"
  echo "  waybar     Print waybar JSON-formatted status"
  exit 1
  ;;
esac
