#!/bin/bash

# Copyright (C) 2013-2025 Marcin Krol <hawk@tld-linux.org>
# All Rights Reserved

. /lib/cri/vars

# read current configuration
. /lib/cri/system.config

dialog_title="System image configuration"

# function to save CRI configuration
save_image_config () {
  cat >/lib/cri/system.config <<EOF
CRI_HOSTNAME="${CRI_HOSTNAME}"
CRI_TIMEZONE="${CRI_TIMEZONE}"
CRI_INSTALL_BOOTLOADER="${CRI_INSTALL_BOOTLOADER}"
CRI_BOOTLOADER_DEVICES="${CRI_BOOTLOADER_DEVICES}"
CRI_CONFIGURE_NETWORK="${CRI_CONFIGURE_NETWORK}"
CRI_DISABLE_NET_IFNAMES="${CRI_DISABLE_NET_IFNAMES}"
CRI_UDEV_NET_RULES="${CRI_UDEV_NET_RULES}"
CRI_ROOT_PASSWORD="$(echo ${CRI_ROOT_PASSWORD} | sed -e 's/\$/\\\$/g;' 2>/dev/null)"
CRI_CREATE_USER="${CRI_CREATE_USER}"
CRI_USER_LOGIN="${CRI_USER_LOGIN}"
CRI_USER_PASSWORD="$(echo ${CRI_USER_PASSWORD} | sed -e 's/\$/\\\$/g;' 2>/dev/null)"
EOF
  return 0
}

# funcion to get CRI_HOSTNAME from user
system_hostname () {
  dialog \
    --backtitle "${dialog_backtitle}" \
    --title "${dialog_title} - system hostname" \
    --colors \
    --cancel-label "Quit" \
    --inputbox "\nEnter hostname:" \
    9 60 \
    "${CRI_HOSTNAME}" \
    2>/tmp/$(basename "${0}.dialog" 2>/dev/null)
  return $?
}

# funcion to get CRI_HOSTNAME from user
timezone () {
  dialog \
    --backtitle "${dialog_backtitle}" \
    --title "${dialog_title} - timezone" \
    --colors \
    --extra-button \
    --extra-label "Choose from list" \
    --cancel-label "Quit" \
    --inputbox "\nEnter timezone manually, choose from list of all timezones or leave empty to use UTC:" \
    10 60 \
    "${CRI_TIMEZONE}" \
    2>/tmp/$(basename "${0}.dialog" 2>/dev/null)
  return $?
}

timezone_list () {
  cat >/tmp/dialog.opts <<EOF
    --backtitle "${dialog_backtitle}"
    --title "${dialog_title}"
    --colors
    --menu "Select timezone:"
      20 60 13
EOF
  for tz in $(find /usr/share/zoneinfo/ -type f 2>/dev/null | sed -e 's!/usr/share/zoneinfo/!!g;' 2>/dev/null | sort -u 2>/dev/null | grep -v -E "^(posix|right|SystemV)" 2>/dev/null | grep -v -E "\.tab$" 2>/dev/null); do
    echo "\"${tz}\" \"\"" >>/tmp/dialog.opts
  done
  dialog --file /tmp/dialog.opts \
    2>/tmp/$(basename "${0}.dialog" 2>/dev/null)
}

# funcions to get CRI_ROOT_PASSWORD
root_password () {
  dialog \
    --backtitle "${dialog_backtitle}" \
    --title "${dialog_title} - root password" \
    --colors \
    --cancel-label "Quit" \
    --insecure \
    --passwordbox "\nEnter password for root:" \
    9 60 \
    2>/tmp/$(basename "${0}.dialog" 2>/dev/null)
  return $?
}

reenter_root_password () {
  dialog \
    --backtitle "${dialog_backtitle}" \
    --title "${dialog_title} - root password" \
    --colors \
    --cancel-label "Quit" \
    --insecure \
    --passwordbox "\nConfirm root password:" \
    9 60 \
    2>/tmp/$(basename "${0}.dialog" 2>/dev/null)
  return $?
}

root_password_is_set () {
  dialog \
    --backtitle "${dialog_backtitle}" \
    --title "${dialog_title} - root password" \
    --colors \
    --extra-button \
    --extra-label "No" \
    --no-label "Quit" \
    --yesno "\nRoot password is already set. Do you want to change it?" \
    8 60 \
    2>/tmp/$(basename "${0}.dialog" 2>/dev/null)
  return $?
}

# funcion to get CRI_CREATE_USER
user_account () {
  dialog \
    --backtitle "${dialog_backtitle}" \
    --title "${dialog_title} - user account" \
    --colors \
    --extra-button \
    --extra-label "No" \
    --no-label "Quit" \
    --yesno "\nCreate account for first user?\n\n\Z1Warning!\Zn If you will choose not to create this account you may not be able to log in remotely to installed system." \
    10 65 \
    2>/tmp/$(basename "${0}.dialog" 2>/dev/null)
  return $?
}

# funcions to get CRI_USER_LOGIN
user_login () {
  dialog \
    --backtitle "${dialog_backtitle}" \
    --title "${dialog_title} - user account" \
    --colors \
    --cancel-label "Quit" \
    --inputbox "\nEnter login name for user:" \
    9 60 \
    "${CRI_USER_LOGIN}" \
    2>/tmp/$(basename "${0}.dialog" 2>/dev/null)
  return $?
}

# funcions to get CRI_USER_PASSWORD
user_password () {
  dialog \
    --backtitle "${dialog_backtitle}" \
    --title "${dialog_title} - user account" \
    --colors \
    --cancel-label "Quit" \
    --insecure \
    --passwordbox "\nEnter password for user:" \
    9 60 \
    2>/tmp/$(basename "${0}.dialog" 2>/dev/null)
  return $?
}

reenter_user_password () {
  dialog \
    --backtitle "${dialog_backtitle}" \
    --title "${dialog_title} - user account" \
    --colors \
    --cancel-label "Quit" \
    --insecure \
    --passwordbox "\nConfirm user password:" \
    9 60 \
    2>/tmp/$(basename "${0}.dialog" 2>/dev/null)
  return $?
}

user_password_is_set () {
  dialog \
    --backtitle "${dialog_backtitle}" \
    --title "${dialog_title} - user account" \
    --colors \
    --extra-button \
    --extra-label "No" \
    --no-label "Quit" \
    --yesno "\nUser password is already set. Do you want to change it?" \
    8 60 \
    2>/tmp/$(basename "${0}.dialog" 2>/dev/null)
  return $?
}

# funcion to get CRI_INSTALL_BOOTLOADER
bootloader () {
  dialog \
    --backtitle "${dialog_backtitle}" \
    --title "${dialog_title} - bootloader installation" \
    --colors \
    --extra-button \
    --extra-label "No" \
    --no-label "Quit" \
    --yesno "\nInstall boot loader after system installation?\n\n\Z1Warning!\Zn This may make your other systems unbootable until you will update your bootloader configuration manually." \
    10 65 \
    2>/tmp/$(basename "${0}.dialog" 2>/dev/null)
  return $?
}

# funcion to get CRI_BOOTLOADER_DEVICES
bootloader_devices () {
  cat >/tmp/dialog.opts <<EOF
    --backtitle "${dialog_backtitle}" \
    --title "${dialog_title} - bootloader installation" \
    --colors \
    --cancel-label "Quit" \
    --checklist "\nPlease select devices on which you want to install bootloader:" \
    19 70 11 \
    $(
      for disk in $(lsblk -r -n -d -o type,name 2>/dev/null | grep -E "^disk" 2>/dev/null | cut -d " " -f 2 2>/dev/null | sort 2>/dev/null); do
        if echo "${CRI_BOOTLOADER_DEVICES}" | grep -q "/dev/${disk}"; then
          echo "\"/dev/${disk}\" \"\" on"
        else
          echo "\"/dev/${disk}\" \"\" off"
        fi
      done
    )
EOF
  dialog --file /tmp/dialog.opts \
    2>/tmp/$(basename "${0}.dialog" 2>/dev/null)
  return $?
}

# funcion to get CRI_CONFIGURE_NETWORK
network_config () {
  dialog \
    --backtitle "${dialog_backtitle}" \
    --title "${dialog_title} - network configuration" \
    --colors \
    --extra-button \
    --extra-label "No" \
    --no-label "Quit" \
    --yesno "\nConfigure network interfaces in installed system based on CRI network configuration?\n\n\Z1Warning!\Zn With no network configuration you will not be able to log in remotely to installed system." \
    11 65 \
    2>/tmp/$(basename "${0}.dialog" 2>/dev/null)
  return $?
}

# funcion to get CRI_DISABLE_NET_IFNAMES
network_ifnames () {
  dialog \
    --backtitle "${dialog_backtitle}" \
    --title "${dialog_title} - network configuration" \
    --colors \
    --extra-button \
    --extra-label "No" \
    --no-label "Quit" \
    --yesno "\nDisable predictable network interface names like ens192 and fallback to legacy names like eth0 in installed system?\n\n\Z1Warning!\Zn If interface names differ between CRI and installed system, network configuration will be invalid." \
    11 65 \
    2>/tmp/$(basename "${0}.dialog" 2>/dev/null)
  return $?
}

# funcion to get CRI_UDEV_NET_RULES
network_rules () {
  dialog \
    --backtitle "${dialog_backtitle}" \
    --title "${dialog_title} - network configuration" \
    --colors \
    --extra-button \
    --extra-label "No" \
    --no-label "Quit" \
    --yesno "\nConfigure udev rules for persistent ethernet interface names in installed system?\n\nThis is strongly recommended if predictable interface names are disabled." \
    11 65 \
    2>/tmp/$(basename "${0}.dialog" 2>/dev/null)
  return $?
}

################################################################################

# get CRI_HOSTNAME
if [ "${1}" = "" ] || [ "${1}" = "-h" ]; then
  while : ; do
    system_hostname
    result=$?
    if [ "${result}" -eq 1 ]; then
      clear
      exit 1
    else
      if [ -z "$(cat /tmp/$(basename "${0}.dialog" 2>/dev/null) 2>/dev/null)" ]; then
        dialog \
          --backtitle "${dialog_backtitle}" \
          --title "${dialog_title} - system hostname\Zn" \
          --colors \
          --msgbox "\n\Z1Error!\Zn\n\nHostname is required." 9 60
      else
        CRI_HOSTNAME=$(cat /tmp/$(basename "${0}.dialog" 2>/dev/null) 2>/dev/null)
        save_image_config
        break
      fi
    fi
  done
fi

# get CRI_TIMEZONE
if [ "${1}" = "" ] || [ "${1}" = "-tz" ]; then
  while : ; do
    timezone
    result=$?
    if [ "${result}" -eq 0 ]; then
      CRI_TIMEZONE=$(cat /tmp/$(basename "${0}.dialog" 2>/dev/null) 2>/dev/null)
      if [ -z "${CRI_TIMEZONE}" ]; then
        CRI_TIMEZONE="UTC"
      fi
      if ! [ -f "/usr/share/zoneinfo/${CRI_TIMEZONE}" ]; then
        dialog \
          --backtitle "${dialog_backtitle}" \
          --title "${dialog_title} - timezone" \
          --colors \
          --msgbox "\n\Z1Error!\Zn\n\nNo such timezone: ${CRI_TIMEZONE}." 9 60
      else
        save_image_config
        break
      fi
    elif [ "${result}" -eq 1 ]; then
      clear
      exit 1
    elif [ "${result}" -eq 3 ]; then
      timezone_list
      CRI_TIMEZONE=$(cat /tmp/$(basename "${0}.dialog" 2>/dev/null) 2>/dev/null)
    fi
  done
fi

# get CRI_ROOT_PASSWORD
if [ "${1}" = "" ] || [ "${1}" = "-r" ]; then
  if [ -n "${CRI_ROOT_PASSWORD}" ]; then
    root_password_is_set
    result=$?
  else
    result=0
  fi
  if [ "${result}" -eq 0 ]; then
    while : ; do
      root_password
      result=$?
      if [ "${result}" -eq 1 ]; then
        clear
        exit 1
      elif [ -z "$(cat /tmp/$(basename "${0}.dialog" 2>/dev/null) 2>/dev/null)" ]; then
        dialog \
          --backtitle "${dialog_backtitle}" \
          --title "${dialog_title} - root password" \
          --colors \
          --msgbox "\n\Z1Error!\Zn\n\nRoot password can't be empty." 9 60
      else
        new_CRI_ROOT_PASSWORD=$(cat /tmp/$(basename "${0}.dialog" 2>/dev/null) 2>/dev/null)
        reenter_root_password
        result=$?
        if [ "${result}" -eq 1 ]; then
          clear
          exit 1
        else
          confirm_CRI_ROOT_PASSWORD=$(cat /tmp/$(basename "${0}.dialog" 2>/dev/null) 2>/dev/null)
          if [ "${new_CRI_ROOT_PASSWORD}" = "${confirm_CRI_ROOT_PASSWORD}" ]; then
            CRI_ROOT_PASSWORD=$(mkpwdhash -m sha-512 "${new_CRI_ROOT_PASSWORD}" 2>/dev/null)
            save_image_config
            break
          else
            dialog \
              --backtitle "${dialog_backtitle}" \
              --title "${dialog_title} - root password" \
              --colors \
              --msgbox "\n\Z1Error!\Zn\n\nPasswords do not match, try again." 9 60
          fi
        fi
      fi
    done
  elif [ "${result}" -eq 1 ]; then
    clear
    exit 1
  fi
fi

# get CRI_CREATE_USER
if [ "${1}" = "" ] || [ "${1}" = "-u" ]; then
  if [ "${2}" = "yes" ]; then
    CRI_CREATE_USER="true"
  elif [ "${2}" = "no" ]; then
    CRI_CREATE_USER="false"
  else
    user_account
    result=$?
    if [ "${result}" -eq 0 ]; then
      CRI_CREATE_USER="true"
    elif [ "${result}" -eq 1 ]; then
      clear
      exit 1
    else
      CRI_CREATE_USER="false"
    fi
  fi
  save_image_config
fi

if [ "${CRI_CREATE_USER}" = "true" ]; then
  # get CRI_USER_LOGIN
  if [ "${1}" = "" ] || [ "${1}" = "-ul" ]; then
    # get CRI_USER_LOGIN
    while : ; do
      user_login
      result=$?
      if [ "${result}" -eq 1 ]; then
        clear
        exit 1
      elif [ -z "$(cat /tmp/$(basename "${0}.dialog" 2>/dev/null) 2>/dev/null)" ]; then
        dialog \
          --backtitle "${dialog_backtitle}" \
          --title "${dialog_title} - user account" \
          --colors \
          --msgbox "\n\Z1Error!\Zn\n\nUser login can't be empty." 9 60
      else
        CRI_USER_LOGIN=$(cat /tmp/$(basename "${0}.dialog" 2>/dev/null) 2>/dev/null)
        save_image_config
        break
      fi
    done
  fi

  # get CRI_USER_PASSWORD
  if [ "${1}" = "" ] || [ "${1}" = "-up" ]; then
    if [ -n "${CRI_USER_PASSWORD}" ]; then
      user_password_is_set
      result=$?
    else
      result=0
    fi
    if [ "${result}" -eq 0 ]; then
      # get CRI_USER_PASSWORD
      while : ; do
        user_password
        result=$?
        if [ "${result}" -eq 1 ]; then
          clear
          exit 1
        elif [ -z "$(cat /tmp/$(basename "${0}.dialog" 2>/dev/null) 2>/dev/null)" ]; then
          dialog \
            --backtitle "${dialog_backtitle}" \
            --title "${dialog_title} - user account" \
            --colors \
            --msgbox "\n\Z1Error!\Zn\n\nUser password can't be empty." 9 60
        else
          new_CRI_USER_PASSWORD=$(cat /tmp/$(basename "${0}.dialog" 2>/dev/null) 2>/dev/null)
          reenter_user_password
          result=$?
          if [ "${result}" -eq 1 ]; then
            clear
            exit 1
          else
            confirm_CRI_USER_PASSWORD=$(cat /tmp/$(basename "${0}.dialog" 2>/dev/null) 2>/dev/null)
            if [ "${new_CRI_USER_PASSWORD}" = "${confirm_CRI_USER_PASSWORD}" ]; then
              CRI_USER_PASSWORD=$(mkpwdhash -m sha-512 "${new_CRI_USER_PASSWORD}" 2>/dev/null)
              save_image_config
              break
            else
              dialog \
                --backtitle "${dialog_backtitle}" \
                --title "${dialog_title} - user account" \
                --colors \
                --msgbox "\n\Z1Error!\Zn\n\nPasswords do not match, try again." 9 60
            fi
          fi
        fi
      done
    elif [ "${result}" -eq 1 ]; then
      clear
      exit 1
    fi
  fi
fi

# get CRI_CONFIGURE_NETWORK
if [ "${1}" = "" ] || [ "${1}" = "-n" ]; then
  if [ "${2}" = "yes" ]; then
    CRI_CONFIGURE_NETWORK="true"
  elif [ "${2}" = "no" ]; then
    CRI_CONFIGURE_NETWORK="false"
  else
    network_config
    result=$?
    if [ "${result}" -eq 0 ]; then
      CRI_CONFIGURE_NETWORK="true"
    elif [ "${result}" -eq 1 ]; then
      clear
      exit 1
    else
      CRI_CONFIGURE_NETWORK="false"
    fi
  fi
  save_image_config
fi

# get CRI_DISABLE_NET_IFNAMES
if [ "${1}" = "" ] || [ "${1}" = "-nn" ]; then
  if [ "${2}" = "yes" ]; then
    CRI_DISABLE_NET_IFNAMES="true"
  elif [ "${2}" = "no" ]; then
    CRI_DISABLE_NET_IFNAMES="false"
  else
    network_ifnames
    result=$?
    if [ "${result}" -eq 0 ]; then
      CRI_DISABLE_NET_IFNAMES="true"
    elif [ "${result}" -eq 1 ]; then
      clear
      exit 1
    else
      CRI_DISABLE_NET_IFNAMES="false"
    fi
  fi
  save_image_config
fi

# get CRI_UDEV_NET_RULES
if [ "${1}" = "" ] || [ "${1}" = "-nr" ]; then
  if [ "${2}" = "yes" ]; then
    CRI_UDEV_NET_RULES="true"
  elif [ "${2}" = "no" ]; then
    CRI_UDEV_NET_RULES="false"
  else
    network_rules
    result=$?
    if [ "${result}" -eq 0 ]; then
      CRI_UDEV_NET_RULES="true"
    elif [ "${result}" -eq 1 ]; then
      clear
      exit 1
    else
      CRI_UDEV_NET_RULES="false"
    fi
  fi
  save_image_config
fi

# get CRI_INSTALL_BOOTLOADER
if [ "${1}" = "" ] || [ "${1}" = "-b" ]; then
  if [ "${2}" = "yes" ]; then
    CRI_INSTALL_BOOTLOADER="true"
  elif [ "${2}" = "no" ]; then
    CRI_INSTALL_BOOTLOADER="false"
  else
    bootloader
    result=$?
    if [ "${result}" -eq 0 ]; then
      CRI_INSTALL_BOOTLOADER="true"
    elif [ "${result}" -eq 1 ]; then
      clear
      exit 1
    else
      CRI_INSTALL_BOOTLOADER="false"
    fi
  fi
  save_image_config
fi

if [ "${CRI_INSTALL_BOOTLOADER}" = "true" ]; then
  # get CRI_BOOTLOADER_DEVICES
  if [ "${1}" = "" ] || [ "${1}" = "-bd" ]; then
    while : ; do
      bootloader_devices
      result=$?
      if [ "${result}" -eq 0 ]; then
        CRI_BOOTLOADER_DEVICES=$(cat /tmp/$(basename "${0}.dialog") 2>/dev/null | sed -e 's/"//g;' 2>/dev/null)
        save_image_config
        break
      elif [ "${result}" -eq 1 ]; then
        clear
        exit 1
      fi
    done
  fi
fi

clear
