#!/bin/bash
#
# The storage script creates dev.json

declare -F vg_free_size > /dev/null || source /var/tmp/install/storage/stutil.sh

create_vg() {
  local vgname pv
  vgname=$(get_unique_vgname "vg")
  pv=$(get_dev .ppv) || return
  wipefs --all "$pv" || return
  pvcreate -ff "$pv" <<< y || return
  sleep 1
  vgcreate "$vgname" "$pv" || return
  sleep 1
  jqd ".pv = \"$pv\""
  jqd ".vgname = \"$vgname\""
}

create_partitions_tasks() {
  local root home swap acc="[]"
  read -r root swap home < <(jq -r '"\(.root//0) \(.swap//0) \(.home//0)"' $installbase/size.json)
  if get_dev_bool .efi.wipe || get_dev_bool .efi.reformat_disk; then
    acc=$(jm "$acc" task=wipe dev=$(get_dev .efi.dev) t=efi)
  fi
  acc=$(jm "$acc" task=create size=$root t=ext4 name=root)
  acc=$(jm "$acc" task=create size=$home t=ext4 name=home)
  acc=$(jm "$acc" task=create size=$swap t=swap name=swap)
  echo "$acc"
}

fresh_install() {
  local tasks
  configure_efi_partition || return
  configure_data_partition || return
  create_vg || return
  init_dev_json || return
  sensible_sizes || return
  tasks="$(create_partitions_tasks)" || return
  run_storage_tasks "$tasks"
}

activate_vg() {
  local vgname pv
  vgname=$(get_dev .vgname)
  pv=$(get_dev .pv)
  vgchange --devices "$pv" -ay "$vgname" || return
  sleep 1
}

should_keep_data_partition() {
  local kname devices data size
  data=$(get_dev .data.disk)
  devices=$(get_pvs_in "$data")
  if [[ -z $devices ]]; then
    return 1
  fi
  if [[ $(wc -l <<< $devices) = "1" ]]; then
    kname=$(get_kname "$devices")
    size=$(lsblk -rn --filter "KNAME == '$kname'" -o SIZE)
    read_nodefault "Should $kname ($size) be the data partition?"
  else
    1>&2 echo "Multiple partitions on $data contain LVM data."
    read_nodefault "Use one of them as the data partition?"
  fi
}

configure_pv() {
  local kname devices data
  data=$(get_dev .data.disk)
  devices=$(get_pvs_in "$data")
  if [[ -z $devices ]]; then
    return 1
  fi
  if [[ $(wc -l <<< $devices) = "1" ]]; then
    1>&2 echo "Using the only PV $devices"
    echo "$devices"
  else
    1>&2 echo "Please select the PV"
    select_arrow "$devices" || return
    get_ui_result
  fi
}

prepare_partitions() {
  local efidisk datadisk tasks again pv
  while :; do
    if [[ $again ]]; then
      read_yn "Retry the partitioning? \"n\" goes back to config" ; rc=$?
      (( rc == 27 )) && continue
      (( rc != 0 )) && return 1
    fi
    again=1
    auto_assemble_raid
    efidisk=$(configure_disk "the disk that will contain the EFI partition") || continue
    datadisk=$(configure_disk "the disk that will contain the data partition") || continue
    jqd ".efi.disk = \"$efidisk\""
    jqd ".data.disk = \"$datadisk\""
    configure_create_label || continue
    if get_dev_bool .data.reformat_disk; then
      rc=1
    elif get_dev_bool .efi.reformat_disk && [[ $datadisk = "$efidisk" ]]; then
      rc=1
    else
      should_keep_data_partition ; rc=$?
      (( rc == 27 )) && continue
    fi
    if ! get_dev_bool .efi.reformat_disk; then
      check_gpt_label "$efidisk" || continue
    fi
    if (( rc != 0 )); then
      fresh_install || continue
      return
    fi
    pv=$(configure_pv) || continue
    jqd ".pv = \"$pv\""
    configure_efi_partition || continue
    configure_vgname || continue
    activate_vg || continue
    configure_lv_roles || continue
    sensible_sizes || continue
    tasks=$(preserve_data_tasks) || continue
    run_storage_tasks "$tasks" || continue
    break
  done
}

storage_main() {
  prepare_partitions || return
  populate_dev_json || return
}

return 2> /dev/null || {
  storage_main
}
