#!/bin/bash
# This script recursively scans the current working directory to build a nested JSON tree.
# Only files with the .cbz extension are included.
#
# Each folder and file is assigned an ID:
#  - The root folder gets id "0".
#  - All other folders get a four-digit ID computed from their name (with a size value of 0).
#  - Files get a four-digit ID computed from a basic hash of the file content.
#
# Each file object also includes a "link" field built from a base URL and the file's relative path.
#
# Modify the file selection logic if you want to include additional file types.

# Base URL for file links.
base_url="https://comic.xora.space"

# Function to escape strings for JSON.
json_escape() {
  echo "$1" | sed 's/\\/\\\\/g; s/"/\\"/g'
}

# Function to URL-encode a string.
url_encode() {
  local string="${1}"
  local encoded=""
  local pos c o
  for (( pos=0; pos<${#string}; pos++ )); do
    c=${string:$pos:1}
    case "$c" in
      [a-zA-Z0-9.~_-]) o="${c}" ;;
      *) printf -v o '%%%02X' "'$c" ;;
    esac
    encoded+="${o}"
  done
  echo "$encoded"
}

# Function to compute a four-digit ID based on a name and size.
# This is used for folders (with size 0).
compute_id() {
  local name="$1"
  local size="$2"
  local input="${name}${size}"
  # Use cksum to get a numeric hash.
  local cksum_value
  cksum_value=$(echo -n "$input" | cksum | awk '{print $1}')
  local id_number=$(( cksum_value % 10000 ))
  # Format with leading zeros to ensure four digits.
  printf "%04d" "$id_number"
}

# Function to compute a four-digit ID for a file based on its content.
compute_file_id() {
  local file="$1"
  local file_hash
  file_hash=$(cksum "$file" | awk '{print $1}')
  local id_number=$(( file_hash % 10000 ))
  printf "%04d" "$id_number"
}

# Recursive function to process a directory.
# Arguments:
#   $1: directory path to process
#   $2: folder name to use in the JSON object
process_directory() {
  local dir="$1"
  local folder_name="$2"
  local children_json=""
  local first=1
  
  # Compute folder ID: if folder_name is "root", use "0"; otherwise compute using size 0.
  local folder_id
  if [ "$folder_name" == "root" ]; then
    folder_id="0"
  else
    folder_id=$(compute_id "$folder_name" "1")
  fi
  
  # Enable nullglob so that if no files match, the glob expands to nothing.
  shopt -s nullglob
  
  # Process each item in the directory.
  for entry in "$dir"/*; do
    if [ -d "$entry" ]; then
      # Process subdirectories recursively.
      local child_name
      child_name="$(basename "$entry")"
      local child_json
      child_json=$(process_directory "$entry" "$child_name")
      if [ $first -eq 0 ]; then
        children_json+=","
      fi
      children_json+="$child_json"
      first=0
    elif [ -f "$entry" ]; then
      # Only process files ending in .cbz.
      if [[ "$entry" == *.cbz ]]; then
        local file_name
        file_name="$(basename "$entry")"
        local extension="cbz"
        local size
        size=$(stat -c%s "$entry")
        # Compute file ID based on a hash of the file content.
        local file_id
        file_id=$(compute_file_id "$entry")
        
        # Compute the relative path from the current directory.
        local rel_path="${entry#$(pwd)/}"
        # URL encode each segment of the relative path so that "/" is preserved.
        IFS='/' read -r -a path_parts <<< "$rel_path"
        local encoded_parts=()
        for part in "${path_parts[@]}"; do
          encoded_parts+=("$(url_encode "$part")")
        done
        local encoded_path
        encoded_path=$(IFS=/; echo "${encoded_parts[*]}")
        local link="${base_url}/${encoded_path}"
        
        local file_json
        file_json="{\"id\": \"$(json_escape "$file_id")\", \"name\": \"$(json_escape "$file_name")\", \"type\": \"file\", \"size\": $size, \"extension\": \"$(json_escape "$extension")\", \"link\": \"$(json_escape "$link")\"}"
        if [ $first -eq 0 ]; then
          children_json+=","
        fi
        children_json+="$file_json"
        first=0
      fi
    fi
  done
  
  shopt -u nullglob
  
  # Build the JSON object for this folder.
  local folder_json
  folder_json="{\"id\": \"$(json_escape "$folder_id")\", \"name\": \"$(json_escape "$folder_name")\", \"type\": \"folder\", \"children\": [${children_json}]}"
  echo "$folder_json"
}

# --- Main script starts here ---
# Process the current working directory as the root.
root_json=$(process_directory "$(pwd)" "root")
echo "$root_json" > contents.json
echo "contents.json generated."
