#!/bin/bash
# - bof - #
# - Version: 1.0.17 - #



<<'comment'
# -  - #
# - Install DataFoldersConfiguration - #

# -  - #
# - Original folder - #
/DataBtrfs/Arch.Img/Arch_Configuration/Data_FoldersConfiguration.Ins/DataFoldersConfiguration.sh


xdg-user-dirs-update;

bash <(curl -s https://www.education.isdevelopment.us/Arch.Ins/Software.Ins/BashFiles.Ins/DataFoldersConfiguration.sh)

# -  - #
# - Timezone setting - #
sudo timedatectl set-timezone America/New_York;
timedatectl;



# - Configured - #

sudo pacman -S eza --noconfirm --needed;
sudo apt install eza -y;



cd ~/;
curl -o ~/sDF_.sh "https://www.education.isdevelopment.us/Arch.Ins/Software.Ins/BashFiles.Ins/DataFoldersConfiguration.sh"
chmod +x ~/sDF_.sh; ~/./sDF_.sh;

cd ~/; rm -rf ~/sDF_.sh; vim ~/sDF_.sh;
copy & paste this content
chmod +x ~/sDF_.sh; ~/./sDF_.sh;



# -  - #
# - Vim commands - #
https://vim.rtorr.com/

rm -rf ~/.bashrc;
nvim ~/.bashrc;

rm -rf ~/.zshrc;
nvim ~/.zshrc;

ssh-keygen -R 192.168.1.1

# - On client - #
cd ~/.ssh;
ssh-keygen -t rsa;

cat ~/.ssh/id_rsa.pub;

# - On server - #
nvim ~/.ssh/authorized_keys;

sudo apt install curl git gparted htop inxi net-tools ntp neovim screenfetch tree -y;
sudo pacman -S curl git gparted htop inxi net-tools ntp neovim screenfetch tree --noconfirm --needed;

sS1_=$(echo $(lsblk -f | grep $sD_) | awk '{print $2;}');
if [ "$sS1_" == "btrfs" ]; then echo $sS1_; else echo "ext4"; fi;
comment



# -  - #
# - Variables_ - #
function Variables_() {
  sData_='Data';
  sDB_='DataBtrfs';
  sDP_='DataPool';
  sUd_=~/.config/user-dirs.dirs;
  sConf_='# - Configured - #';
  sFs_=/etc/fstab;

  sDc_=/Documents;
  hDc_=~/Documents;

  sDw_=/Downloads;
  hDw_=~/Downloads;

  sM_=/Music;
  hM_=~/Music;

  sP_=/Pictures;
  hP_=~/Pictures;

  sV_=/Videos;
  hV_=~/Videos;

  sTsfa_=/ToShare-FullAccess;
  sTsjr_=/ToShare-JustRead;
}



# -  - #
# - lookData_ - #
function lookData_() {
    # 1. Check for Btrfs data location /DataBtrfs
    if findmnt -n "/$sDB_" >/dev/null 2>&1; then
        echo "$sDB_"
        return
    fi

    # 2. Check for ZFS pool named "DataPool"
    if command -v zpool >/dev/null 2>&1 && zpool list DataPool >/dev/null 2>&1; then
        echo "$sDP_"
        return
    fi

    # 3. Fallback to /Data
    echo "$sData_"
}



# -  - #
# - _dialog_colors_ - Write custom dialogrc to a temp file and return the path - #
function _dialog_colors_() {
    local tmp_rc=$(mktemp /tmp/dialogrc.XXXXXX)
    cat > "$tmp_rc" << 'DIALOGRC'
use_shadow = ON
use_colors = ON
screen_color = (CYAN,BLACK,ON)
shadow_color = (BLACK,BLACK,ON)
dialog_color = (BLACK,WHITE,OFF)
title_color = (BLUE,WHITE,ON)
border_color = (WHITE,WHITE,ON)
button_active_color = (WHITE,BLACK,ON)
button_inactive_color = dialog_color
button_key_active_color = button_active_color
button_key_inactive_color = (RED,WHITE,OFF)
button_label_active_color = (YELLOW,BLACK,ON)
button_label_inactive_color = (BLACK,WHITE,ON)
menubox_color = dialog_color
menubox_border_color = border_color
item_color = dialog_color
item_selected_color = button_active_color
tag_color = title_color
tag_selected_color = button_label_active_color
tag_key_color = button_key_inactive_color
tag_key_selected_color = (RED,BLACK,ON)
check_color = dialog_color
check_selected_color = button_active_color
itemhelp_color = (WHITE,BLACK,OFF)
form_item_readonly_color = (CYAN,WHITE,ON)
menubox_border2_color = dialog_color
DIALOGRC
    echo "$tmp_rc"
    return 0
}



# -  - #
# - ensure_dialog_ - Ensure dialog package is installed for the interactive menu - #
function ensure_dialog_() {
    if ! command -v dialog &>/dev/null; then
        echo -e "\033[1;33m► dialog not found. Installing...\033[0m"
        sudo apt-get update -qq 2>/dev/null || sudo pacman -S --noconfirm dialog 2>/dev/null
        sudo apt-get install -y dialog 2>/dev/null
        if ! command -v dialog &>/dev/null; then
            echo -e "\033[1;33m⚠ dialog installation failed. Falling back to numbered selection.\033[0m"
            return 1
        fi
        echo -e "\033[1;32m✅ dialog installed successfully.\033[0m"
    fi
    return 0
}



# -  - #
# - selectDataTarget_ - Show interactive menu of available data locations to configure - #
# -   Returns: selected data name (DataBtrfs, DataPool, or Data) or empty on cancel - #
function selectDataTarget_() {
    ensure_dialog_ >&2

    local -a candidates=()
    local -a dialog_args=()

    # Detect available data locations
    if findmnt -n "/$sDB_" >/dev/null 2>&1; then
        local btrfs_size=$(df -h "/$sDB_" 2>/dev/null | awk 'NR==2{print $2}')
        candidates+=("/$sDB_|btrfs|$btrfs_size|$sDB_")
    fi
    if command -v zpool >/dev/null 2>&1 && zpool list DataPool >/dev/null 2>&1; then
        local pool_size=$(zpool list -H -o size DataPool 2>/dev/null)
        candidates+=("/$sDP_|zfs|$pool_size|$sDP_")
    fi
    if findmnt -n "/$sData_" >/dev/null 2>&1; then
        local data_size=$(df -h "/$sData_" 2>/dev/null | awk 'NR==2{print $2}')
        candidates+=("/$sData_|ext4|$data_size|$sData_")
    fi

    if [[ ${#candidates[@]} -eq 0 ]]; then
        echo ""
        return 1
    fi

    local item_count=0
    local first=""
    for item in "${candidates[@]}"; do
        local path=$(echo "$item" | cut -d'|' -f1)
        local fstype=$(echo "$item" | cut -d'|' -f2)
        local size=$(echo "$item" | cut -d'|' -f3)
        local label="${path}  (${fstype}, ${size})"
        dialog_args+=("$path" "$label" "off")
        item_count=$((item_count + 1))
    done

    # Default: select first item
    if [[ $item_count -gt 0 ]]; then
        dialog_args[2]="on"
    fi

    local tmp_rc=$(_dialog_colors_)
    local result_file=$(mktemp /tmp/dialog_result.XXXXXX)
    DIALOGRC="$tmp_rc" dialog --stdout --title "Available Data Locations" \
        --radiolist "Select the data location to configure folders on:" \
        0 0 $item_count "${dialog_args[@]}" 2>"$result_file"
    rm -f "$tmp_rc"
    local exit_code=$?
    local result=$(cat "$result_file" | tr -d '\n\r' | xargs echo -n)
    rm -f "$result_file"

    if [[ $exit_code -ne 0 ]] || [[ -z "$result" ]]; then
        echo ""
        return 1
    fi

    # Return the data NAME (DataBtrfs / DataPool / Data) matching the selected path
    for item in "${candidates[@]}"; do
        local path=$(echo "$item" | cut -d'|' -f1)
        local name=$(echo "$item" | cut -d'|' -f4)
        if [[ "$path" == "$result" ]]; then
            echo "$name"
            return 0
        fi
    done

    echo ""
    return 1
}



# -  - #
# - DocumentsFolders_ - #
function DocumentsFolders_(){
  local sU_=$USER \
        sD_=/"$1";

  # -  - #
  # - Configure Data folders - #

  if [[ ! -d "$sD_" ]]; then
    sudo mkdir $sD_; fi;

  sudo chown -R $sU_:$sU_ $sD_;
  chmod -R 775 $sD_;

  # -  - #
  # - Create Documents & Images folders based on filesystem type - #
  case "$1" in
    "$sDP_")
      # ZFS: create datasets
      echo -e "\n► Creating ZFS datasets under $sD_..."
      if zfs list "$sDP_/Documents" >/dev/null 2>&1; then
        echo "  ℹ️  Already exists: DataPool/Documents"
      else
        sudo zfs create -o mountpoint=$sD_$sDc_ $sDP_/Documents && echo "  ✅ Created: DataPool/Documents" || { echo "  ❌  ZFS create failed: DataPool/Documents"; exit 1; }
      fi
      for ds in Downloads Music Pictures Videos ToShare-FullAccess ToShare-JustRead; do
        if zfs list "$sDP_/Documents/$ds" >/dev/null 2>&1; then
          echo "  ℹ️  Already exists: DataPool/Documents/$ds"
        else
          sudo zfs create "$sDP_/Documents/$ds" && echo "  ✅ Created: DataPool/Documents/$ds" || { echo "  ❌  ZFS create failed: DataPool/Documents/$ds"; exit 1; }
        fi
      done
      if zfs list "$sDP_/Images" >/dev/null 2>&1; then
        echo "  ℹ️  Already exists: DataPool/Images"
      else
        sudo zfs create -o mountpoint=$sD_/Images $sDP_/Images && echo "  ✅ Created: DataPool/Images" || { echo "  ❌  ZFS create failed: DataPool/Images"; exit 1; }
      fi
      for ds in Backup Programs VManager; do
        if zfs list "$sDP_/Images/$ds" >/dev/null 2>&1; then
          echo "  ℹ️  Already exists: DataPool/Images/$ds"
        else
          sudo zfs create "$sDP_/Images/$ds" && echo "  ✅ Created: DataPool/Images/$ds" || { echo "  ❌  ZFS create failed: DataPool/Images/$ds"; exit 1; }
        fi
      done
      # Enable POSIX ACLs on ZFS pool for setfacl support
      sudo zfs set acltype=posixacl DataPool 2>/dev/null
      sudo zfs set xattr=sa DataPool 2>/dev/null

      # Fallback to mkdir for any missing paths
      [ ! -d "$sD_$sDc_" ] && sudo mkdir -p "$sD_$sDc_"
      [ ! -d "$sD_/Images" ] && sudo mkdir -p "$sD_/Images"
      ;;
    "$sDB_")
      # Btrfs: create subvolumes with proper nesting
      echo -e "▶ Creating Btrfs subvolumes under $sD_..."
      create_btrfs_subvol_() {
        local target="$1"
        # Already a subvolume?
        if sudo btrfs subvolume show "$target" &>/dev/null; then
          echo "  ℹ️  Already a subvolume: $target"
          return 0
        fi
        # Plain directory exists?
        if [[ -d "$target" ]]; then
          if [[ -n "$(ls -A "$target" 2>/dev/null)" ]]; then
            echo "  ⚠️  $target exists as a non-empty directory. Skipping (convert manually)."
            return 1
          fi
          echo "  ⚠️  Removing empty directory to create subvolume: $target"
          sudo rmdir "$target"
        fi
        if sudo btrfs subvolume create "$target" >/dev/null 2>&1; then
          echo "  ✅ Created subvolume: $target"
          return 0
        else
          echo "  ❌ Failed to create subvolume: $target"
          return 1
        fi
      }
      # First level: Documents, Images
      for sv in Documents Images; do
        create_btrfs_subvol_ "$sD_/$sv"
      done
      # Second level: inside Documents
      for sv in Downloads Music Pictures Videos ToShare-FullAccess ToShare-JustRead; do
        create_btrfs_subvol_ "$sD_/Documents/$sv"
      done
      # Second level: inside Images
      for sv in Backup Programs VManager; do
        create_btrfs_subvol_ "$sD_/Images/$sv"
      done
      unset -f create_btrfs_subvol_
      ;;
    *)
      # ext4 (default): create regular directories
      echo -e "\n► Creating ext4 directory structure under $sD_..."
      for d in "$sD_$sDc_" "$sD_$sDc_$sDw_" "$sD_$sDc_$sM_" "$sD_$sDc_$sP_" "$sD_$sDc_$sV_" "$sD_/Images" "$sD_/Images/Backup" "$sD_/Images/Programs" "$sD_/Images/VManager"; do
        if [[ -d "$d" ]]; then
          echo "  ℹ️  Already exists: $d"
        else
          mkdir -p "$d" && echo "  ✅ Created: $d"
        fi
      done
      ;;
  esac

  # -  - #
  # - Remove original Documents & links - #
  sudo rm -rf $hDc_ $hDw_ $hM_ $hP_ $hV_;

  # -  - #
  # - Create new Documents links - #
  ln -s $sD_$sDc_ $hDc_;
  ln -s $sD_$sDc_$sDw_ $hDw_;
  ln -s $sD_$sDc_$sM_ $hM_;
  ln -s $sD_$sDc_$sP_ $hP_;
  ln -s $sD_$sDc_$sV_ $hV_;

  # -  - #
  # - Create samba folders (fallback if not created via zfs/btrfs above) - #
  if [[ ! -d "$sD_$sDc_$sTsfa_" ]]; then
    mkdir -p $sD_$sDc_$sTsfa_;
  fi
  if [[ ! -d "$sD_$sDc_$sTsjr_" ]]; then
    mkdir -p $sD_$sDc_$sTsjr_;
  fi

  # -  - #
  # - Make public samba folders - #

  # -  - #
  # - Set ownership for everything created - #
  sudo chown -R $sU_:$sU_ $sD_;
  
  # -  - #
  # - Make public samba folders - #
  chmod 777 $sD_$sDc_$sTsfa_;
  chmod 777 $sD_$sDc_$sTsjr_;
}



# -  - #
# - uDirDir_ - #
function uDirDir_(){
  local sD_=/$1;

  # -  - #
  # - Redirect $USER folders - #
  echo -e "\nDeleting $sUd_ file...";
  mkdir -p ~/.config;
  rm -rf $sUd_;

  echo -e "\nCreating new $sUd_ file..."

cat <<EOT >> $sUd_;

# -  - #
$sConf_
# - vim ~/.config/user-dirs.dirs - #
# -  - #

XDG_DOCUMENTS_DIR="$sD_$sDc_"
XDG_DOWNLOAD_DIR="$sD_$sDc_$sDw_"
XDG_MUSIC_DIR="$sD_$sDc_$sM_"
XDG_PICTURES_DIR="$sD_$sDc_$sP_"
XDG_VIDEOS_DIR="$sD_$sDc_$sV_"

EOT

sed -i '7 i XDG_DESKTOP_DIR="$HOME/Desktop"' $sUd_;
sed -i '8 i XDG_TEMPLATES_DIR="$HOME/Templates"' $sUd_;
sed -i '9 i XDG_PUBLICSHARE_DIR="$HOME/Public"' $sUd_;
}



# -  - #
# - Main_ - #
function Main_(){

# Flush any paste-buffer residual before interactive prompt
while read -r -t 0.01 flush 2>/dev/null; do : ; done

# Show interactive menu of available data locations
local dPart_
dPart_=$(selectDataTarget_)
if [[ -z "$dPart_" ]]; then
  echo -e "\n\033[1;31m❌ No data location selected or operation cancelled.\033[0m"
  return 1
fi

echo -e "\nConfiguring Documents directories on \033[1;33m$dPart_\033[0m...\n\n";

read -r -p $'Type \033[1;33mYES\033[0m to proceed with folder configuration: ' sConfirm_;
if [[ "$sConfirm_" == "YES" ]]; then
  DocumentsFolders_ $dPart_; 
  uDirDir_ $dPart_;

  # -  - #
  # - Configure /Data directory: setgid + ACL defaults - #
  # New files/dirs inherit group, maintain group-write permissions
  
  echo -e "\n\nData partition:  /$dPart_\n\n"

  if [[ -d "/$dPart_" ]]; then
    sudo apt install acl -y 2>/dev/null || sudo pacman -S --noconfirm --needed acl 2>/dev/null || sudo dnf install acl -y 2>/dev/null

    echo -e "\n"

    sudo chmod g+s "/$dPart_" 2>/dev/null
    sudo setfacl -d -m g::rwx "/$dPart_" 2>/dev/null
    sudo setfacl -d -m d:g::rwx "/$dPart_" 2>/dev/null

    echo -e "Command:  ls -ld /$dPart_:\n"
    ls -ld /$dPart_;
    echo -e "\n\nCommand:  getfacl /$dPart_:\n"
    getfacl /$dPart_;
  fi

  echo -e "\n✅ Documents directories configured successfully...\n";
else
  echo -e "\n❌ Operation cancelled by user.\n";
fi;
}



clear;
Variables_;
Main_;



rm -rf ~/sDF_.sh;



<<'comment'
cd ~/; rm -rf ~/sDF_.sh; vim ~/sDF_.sh;
copy & paste this content
chmod +x ~/sDF_.sh; ~/./sDF_.sh;
comment



# - eof - #