#!/usr/bin/env bash

# Copyright 2014 Calimero <calimeroteknik@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.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.


# Folder for the resource files this uses
resource_folder='/usr/share/ctkarch-sysconfig'

export DIALOGRC="${resource_folder}/dialogrc"
maxheight="$(($(tput lines)-5))"; [ -z "$maxheight" ] && maxheight=$((25-4))

mydialog() { dialog --backtitle "$_backtitle" "$@"; }

dialogmenu() {
  local width=72
  local nbitems=$((${#items[*]}/2))
  local height=$((nbitems+6+(${#_hint}-1)/(width-4)))
  [[ $_hint ]] && ((height++))
  [ "$height" -ge "$maxheight" ] && height="$maxheight"
  mydialog --title "$_title" --cancel-label "$_exit" --ok-label "$_ok" "$@" \
         --no-tags --menu "$_hint" "$height" "$width" \
         "$nbitems" "${items[@]}"
}

chroot_command() {
  if [[ "$systemroot" =~ ^/*$ ]];then
    "$@"
    return $?
  else
    [[ "$UID" == 0 ]] || { echo "$1 : $_needsroot" >&2; return 1; }
    local i mymounts
    for i in dev dev/pts proc sys;do
      if ! grep -q "${systemroot}/$i" /proc/mounts ;then
        mount -o bind "/$i" "${systemroot}/$i" || return 1
        mymounts+=("${systemroot}/$i")
      fi
    done
    chroot "${systemroot}" "$@"
    local ret=$?
    for (( i=${#mymounts[@]}-1; i>=0; i-- ));do umount "${mymounts[i]}";done
    return $ret
  fi
}

interactive() {
  # Set a file descriptor to display things on stdout
  exec 3>&1

  # If language selection used the fallback
  if [ -n "$lang_unsure" ]; then
    source "${resource_folder}/i18n/${deflang}"
    local items _title="$_picklang"
    for l in $(cd "${resource_folder}/i18n"; echo *); do
      items+=("$l" "$l")
    done
    lang="$(dialogmenu --nocancel 2>&1>&3)"
    unset items _title
    lang="${lang:-"$deflang"}"
    source "${resource_folder}/i18n/${lang}" || exit 1
  fi

  local item items=()

  for item in "${resource_folder}/modules"/* ;do
    items+=( "${item##*/}" "$(unset _title; source "${item}/i18n/${lang}"; echo "${_title:-"${item##*/} - $_moduleloaderror"}")" )
  done

  item="${items[0]}"
  while
    item="$(dialogmenu --default-item "$item" 2>&1>&3)"
    [[ "$item" != '' ]]
  do (
    _exit="$_back"
    if ! err="$(unset items
                source "${resource_folder}/modules/${item}/functions" 2>&1 || exit 1
                source "${resource_folder}/modules/${item}/i18n/${lang}" 2>&1 || source "${resource_folder}/modules/${item}/i18n/${deflang}" 2>&1 || exit 1
                err="$(type menu 2>&1>/dev/null)" || { mydialog --msgbox "${_menuloaderror}\n\n${err}" 10 72 >&3; exit 0; }
                moduledir="${resource_folder}/modules/${item}" menu >&3)"
    then
      mydialog --msgbox "${_moduleloaderror}\n\n${err}" 10 72
    fi
  ) done
  clear
}

setdefaults() {
  local ret=0

  local module
  for module in "${resource_folder}/modules"/* ;do
    echo ":: Module ${module##*/}..."
    (
      source "${module}/i18n/${lang}" || source "${module}/i18n/${deflang}"
      source "${module}/functions" && defaults
    ) \
      || { echo ":: Module ${module##*/} FAILED"; ret=1; }
  done

  return $ret
}

# API function call
# parms: module::setfunc parm...
call() {
  local module="${resource_folder}/modules/${1%::*}" function="${1#*::}"
  shift

  echo ":: Running ${module##*/}::${function}$(for i in "$@";do printf " '$i'";done)"
  (
    source "${module}/i18n/${lang}" || source "${module}/i18n/${deflang}" || echo 'Cannot load locale for the module!' >&2
    source "${module}/functions" && "$function" "$@" || exit 1
  ) \
    || { echo ":: ${module##*/}::${function} FAILED"; return 1; }

  return 0
}

main() {
  # Localization
  deflang='en' # English is the fallback

  # Uninteractively set the language, based on $LANG, or use the fallback
  lang="${LANG%_*}"
  if [ -z "$lang" -o ! -f "${resource_folder}/i18n/${lang}" ]; then
    lang_unsure=1
    lang="$deflang"
  fi
  source "${resource_folder}/i18n/${lang}" || exit 1

  # Parse arguments
  while [[ "$1" ]];do
    case "$optmark" in
      '--root')
        systemroot="$1"
        optmark=''
      ;;
      *) case "$1" in
           'call')        shift; call "$@"; exit=0; break; ;;
           'setdefaults') action=setdefaults ;;
           'interactive') action=interactive ;;
           '-h')          echo "$_usage"; exit=0; break ;;
           '--help')      echo "$_usage"; exit=0; break ;;
           '-r')          optmark='--root' ;;
           '--root')      optmark='--root' ;;
           *)             echo "${1}: ${_badarg}" >&2; exit=1; break ;;
         esac
      ;;
    esac
    shift
  done
  if [[ -n "$optmark" ]];then
    echo "$optmark $_requiresarg"
    exit 1
  fi
  [[ -n "$exit" ]] && exit "$exit"

  # Run specified action; if none, the default one
  ${action:-interactive}
}

main "$@"
