# This file is part of ctkarch-sysconfig.
#
# ctkarch-sysconfig 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.

menu() {
  local items=('chpacmanmirror'   "$_pacmanmirror"
               'chifacenaming'    "$_ifacenaming"
               'chdhcpforever'    "$_dhcpforever"
               'chsysrq'          "$_sysrq"
               'chmoresysctl'     "$_moresysctl"
               'chmakepkgthreads' "$_makepkgthreads")
  local item="${items[0]}" err
  while
    item="$(dialogmenu --default-item "$item" 2>&1>&3)"
    [[ "$item" != '' ]]
  do
    err="$("$item" 2>&1>&3)" || mydialog --msgbox "${err}" 10 72
  done
  return 0
}

defaults() {
  # Do nothing for the pacman mirror but compensate with candies
  grep ILoveCandy "${systemroot}/etc/pacman.conf" &>/dev/null || sed -i '/^[#[:space:]]*CheckSpace$/aILoveCandy' "${systemroot}/etc/pacman.conf"

  # Default settings are for one-network-interface machines, so this is fine.
  setifacenaming ethwlan || echo 'setifacenaming FAILED' >&2

  # Enable SysRQ
  setsysrq enable || echo 'setsysrq FAILED' >&2

  # Add a free config file for more sysctl parameters
  setmoresysctl yes || echo 'setmoresysctl FAILED' >&2

  # Automagically set to the number of processor threads on the system
  setmakepkgthreads || echo 'setmakepkgthreads FAILED' >&2

  # By default, make interface-bound dhcpcd services persistent as well
  setdhcpforever yes || echo 'setdhcpforever FAILED' >&2
}

chpacmanmirror() {
  local items item _title="$_pacmanmirror"
  items=('mirrorlist' "$_pickfrommirrorlist"
         'arm'        "$_usearm")
  if item="$(dialogmenu --default-item "$item" 2>&1>&3)";then
    case "$item" in
      'mirrorlist')
        chmirrorlist || return 1
      ;;
      'arm')
        chusearm || return 1
      ;;
    esac
  fi
}

chmirrorlist() {
  local items country mirror _title="$_pickfrommirrorlist" IFS=$'\n'
  for i in $(sed -n '/^$/N;s/\n## //p' "${systemroot}/etc/pacman.d/mirrorlist");do
    items+=("$i" "$i")
  done
  if country="$(dialogmenu 2>&1>&3)";then
    items=()
    shopt -s extglob
    for i in $(sed -n "/^$/N;/^\n## ${country}/,/^\n## /{/[#[:space:]]*Server[[:space:]]*=/p}" "${systemroot}/etc/pacman.d/mirrorlist");do
      items+=("$i" "${i/*([#[:space:]])Server*([[:space:]])=*([[:space:]])/}")
    done
    shopt -u extglob
    if line="$(dialogmenu 2>&1>&3)";then
      shopt -s extglob
      line="${line##*([#[:space:]])}"
      shopt -u extglob
      setpacmanmirror "$line" || return 1
      mydialog --msgbox "$_explain_pacmanmirror" 10 72
    fi
  fi
}

chusearm() {
  local date armurl='http://seblu.net/a/arm' datemin='2013/08/31'
  if date="$(mydialog --date-format '%Y/%m/%d' --calendar "$_arm" 3 40 2>&1>&3)" ;then
    [ "${date//\//}" -ge "${datemin//\//}" ] || { echo "$(printf "$_tooancient" "$datemin")" >&2; return 1; }
    setpacmanmirror "Server = ${armurl}/${date}/\$repo/os/\$arch" || return 1
    mydialog --msgbox "$_explain_pacmanmirror" 10 72
  fi
}

# Set pacman mirror in mirrorlist
# parm: mirror_line
setpacmanmirror() {
  # make sure everything is commented
  sed -Ei 's/^[[:space:]]*([^#[:space:]])/#\1/' "${systemroot}/etc/pacman.d/mirrorlist" || return 1

  # add it if we don't seem to have it already
  if ! grep -q "^[#[:space:]]*${1}" "${systemroot}/etc/pacman.d/mirrorlist" ;then
    if grep '^## Custom mirror$' "${systemroot}/etc/pacman.d/mirrorlist" ;then
      # prepend in the section if present
      sed -i "0,/^## Custom mirror$/s|\(## Custom mirror\)|\1\n${1}|" "${systemroot}/etc/pacman.d/mirrorlist" || return 1
    else
      # add the section if not present
      echo '## Custom mirror' >> "${systemroot}/etc/pacman.d/mirrorlist" || return 1
      echo "${1}" >> "${systemroot}/etc/pacman.d/mirrorlist" || return 1
    fi
  else
    # uncomment the line given as the param (it exists)
    sed -i "s|^[#[:space:]]*\(${1}\)|\1|" "${systemroot}/etc/pacman.d/mirrorlist" || return 1
  fi
  echo "pacman mirror: ${1}"
}

chifacenaming() {
  local items=('ethwlan' 'ethX / wlanX'
               'enpwlp'  'enpXsY / wlpXsY')
  local naming _title="$_ifacenaming"
  if naming="$(dialogmenu 2>&1>&3)";then
    setifacenaming "$naming" || return 1
    mydialog --msgbox "$_explain_ifacenaming" 10 72
  fi
}

# Set the naming style for network interfaces
# parm: {ethwlan/enpwlp}
setifacenaming() {
  if [[ "$1" == 'ethwlan' ]];then
    ln -sf /dev/null "${systemroot}/etc/udev/rules.d/80-net-name-slot.rules" || return 1
  elif [[ "$1" == 'enpwlp' ]];then
    rm -f "${systemroot}/etc/udev/rules.d/80-net-name-slot.rules" || return 1
  else
    echo "invalid parameter '$1'" >&2
    return 1
  fi
  echo "network interface naming: $1"
}

chdhcpforever() {
  local items=('yes' "$_dhcpforever_yes"
               'no'  "$_dhcpforever_no")
  local naming _title="$_dhcpforever"
  if naming="$(dialogmenu 2>&1>&3)";then
    setdhcpforever "$naming" || return 1
    mydialog --msgbox "$_explain_dhcpforever" 10 72
  fi
}

# Make interface-bound dhcpcd retry forever instead of giving up after 30s
# parm: yes|no
setdhcpforever() {
  case "$1" in
    'yes')
      mkdir "${systemroot}/etc/systemd/system/dhcpcd@.service.d" || return 1
      printf '[Service]\nRestart=always\n' > "${systemroot}/etc/systemd/system/dhcpcd@.service.d/retry-forever.conf" || return 1
    ;;
    'no')
     rm -f "${systemroot}/etc/systemd/system/dhcpcd@.service.d/retry-forever.conf" || return 1
     rmdir "${systemroot}/etc/systemd/system/dhcpcd@.service.d"
    ;;
    *) echo "invalid parameter '$1'" >&2; return 1 ;;
  esac
  echo "persistent interface-bound dhcpcd: $1"
}

chsysrq() {
  local items=('dispconf' "$_displaysysrqconf"
               'enable'   "$_enablesysrq"
               'disable'  "$_disablesysrq")
  local choice _title="$_sysrq"
  while choice="$(dialogmenu 2>&1>&3)";do
    case "$choice" in
      'dispconf')
        local lines="$(wc -l < "${moduledir}/res/99-sysrq.conf")"
        (( maxheight > lines+5 )) && local maxheight="$((lines+5))"
        mydialog --textbox "${moduledir}/res/99-sysrq.conf" "$maxheight" 72
      ;;
      'enable')
        setsysrq enable || return 1
        local donestuff=1
      ;;
      'disable')
        setsysrq disable || return 1
        local donestuff=1
      ;;
    esac
    [ -n "$donestuff" ] && { mydialog --msgbox "$_explain_sysrq" 10 72; return 0; }
  done
  return 0
}

# Enable or disable SysRQ keys
# parm: enable|disable
setsysrq() {
  case "$1" in
    'enable')  install -m644 "${moduledir}/res/99-sysrq.conf" "${systemroot}/etc/sysctl.d/99-sysrq.conf" || return 1 ;;
    'disable') rm -f "${systemroot}/etc/sysctl.d/99-sysrq.conf" || return 1 ;;
    *)         echo "invalid parameter '$1'" >&2; return 1 ;;
  esac
  echo "sysrq: ${1}d"
}

chmoresysctl() {
  local items=('yes' "$_enablemoresysctl"
               'no'  "$_removemoresysctl")
  local choice _title="$_moresysctl"
  if choice="$(dialogmenu 2>&1>&3)";then
    case "$choice" in
      'yes')
        setmoresysctl yes || return 1

        local lines="$(wc -l < "${systemroot}/etc/sysctl.d/99-custom.conf")"
        (( maxheight > lines+6 )) && local maxheight="$((lines+6))"
        local contents
        contents="$(mydialog --title "/etc/sysctl.d/99-custom.conf - $_tabforbuttons" --editbox "${systemroot}/etc/sysctl.d/99-custom.conf" "$maxheight" 72 2>&1>&3)" && \
          { echo "$contents" > "${systemroot}/etc/sysctl.d/99-custom.conf" || return 1; }
      ;;
      'no')
        setmoresysctl no || return 1
      ;;
    esac
  fi
  return 0
}

# Add or remove a file with (commented) various sysctl options
# parm: yes|no
setmoresysctl() {
  case "$1" in
    'yes') [ ! -f "${systemroot}/etc/sysctl.d/99-custom.conf" ] && { install -m644 "${moduledir}/res/99-custom.conf" "${systemroot}/etc/sysctl.d/99-custom.conf" || return 1; } ;;
    'no')  rm -f "${systemroot}/etc/sysctl.d/99-custom.conf" || return 1 ;;
    *)     echo "invalid parameter '$1'" >&2; return 1 ;;
  esac
  echo "extra sysctl config: $1"
}

chmakepkgthreads() {
  local threads="$(grep -c processor /proc/cpuinfo)"
  [ -z "$threads" ] && threads=2
  if threads="$(mydialog --title "$_makepkgthreads" --inputbox "$_autothreadsvalue" 6 70 "$threads" 2>&1>&3)";then
    setmakepkgthreads "$threads" || return 1
    mydialog --msgbox "$_explain_makepkgthreads" 10 72
  fi
}

# Set a provided, or nice number of compiler threads in /etc/makepkg.conf
# parm: [nbthreads]
setmakepkgthreads() {
  grep -q '^[[:space:]#]*MAKEFLAGS=' "${systemroot}/etc/makepkg.conf" || { echo "$_makeflagsnotfound" >&2; return 1; }

  local ccthreads
  if [ -n "$1" ];then
    [[ "$1" =~ ^[0-9]+$ ]] || { echo 'NaN' >&2; return 1; }
    ccthreads="$1"
  else
    ccthreads="$(grep -c processor /proc/cpuinfo)" || return 1
  fi

  if grep -q '^[[:space:]]*MAKEFLAGS=.*-j[0-9]*' "${systemroot}/etc/makepkg.conf";then
    # uncommented line(s) with MAKEFLAGS=.*-j[0-9]*, change it/them
    sed -Ei "/^[[:space:]]*MAKEFLAGS=/s/-j[0-9]+/-j${ccthreads}/" "${systemroot}/etc/makepkg.conf" || return 1

  elif grep -q "^[[:space:]]*MAKEFLAGS=.*[\"'][[:space:]]*\$" "${systemroot}/etc/makepkg.conf";then
    # uncommented line(s) with MAKEFLAGS=.*" or MAKEFLAGS=.*', change them
    sed -Ei "s/^([[:space:]]*MAKEFLAGS=.*)([\"'])[[:space:]]*\$/\1 -j${ccthreads}\2/
             ta;b;:a;s/^([[:space:]]*MAKEFLAGS=[\"']) (-j[0-9]+)/\1\2/" "${systemroot}/etc/makepkg.conf" || return 1

  elif grep -q '^[[:space:]#]*MAKEFLAGS=.*-j[0-9]*' "${systemroot}/etc/makepkg.conf";then
    # commented line(s) with MAKEFLAGS=.*-j[0-9]*, change the first one found and uncomment it
    sed -Ei "0,/^[[:space:]#]*MAKEFLAGS=.*-j[0-9]+/{s/-j[0-9]+/-j${ccthreads}/;ta;b;:a;s/^[[:space:]#]//}" "${systemroot}/etc/makepkg.conf" || return 1
  else
    # (guaranteed by earlier check) commented line(s) with MAKEFLAGS=.*", change the first one found and uncomment it
    sed -Ei "0,/^[[:space:]#]*MAKEFLAGS=.*[\"'][[:space:]]*\$/s/^[[:space:]#]*(MAKEFLAGS=.*)([\"'])[[:space:]]*\$/\1 -j${ccthreads}\2/
             ta;b;:a;s/^([[:space:]]*MAKEFLAGS=[\"']) (-j[0-9]+)/\1\2/" "${systemroot}/etc/makepkg.conf" || return 1
  fi

  echo "makepkg compiler threads: ${ccthreads}"
}
