#!/bin/bash
# Exit on error
set -e
##################################################################################################################
#   Custom Arch ISO Builder Script (Linux Version)
##################################################################################################################

# Get absolute path of script directory
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

# Setting general parameters
buildFolder="$SCRIPT_DIR/build"
outFolder="$SCRIPT_DIR/out"
dockerImageName="arch-iso-builder-base"
dockerContainerName="arch-iso-builder-base-container"

# Get current user ID and group ID
HOST_UID=$(id -u)
HOST_GID=$(id -g)

# Check if Docker is installed
if ! command -v docker &> /dev/null; then
    echo "Docker is not installed. Installing Docker..."
    sudo pacman -S --noconfirm docker
    
    # Start and enable Docker service
    echo "Starting Docker service..."
    sudo systemctl start docker
    sudo systemctl enable docker
    
    # Add current user to docker group to avoid using sudo
    echo "Adding current user to docker group..."
    sudo usermod -aG docker $(whoami)
    
    echo "Docker installation completed. You may need to log out and back in for group changes to take effect."
    echo "Continuing with Docker as root for now..."
fi

# Check if Docker daemon is running
if ! docker info &> /dev/null; then
    echo "Docker daemon is not running. Starting Docker service..."
    sudo systemctl start docker
    
    # Wait for Docker daemon to start (with timeout)
    echo "Waiting for Docker daemon to start..."
    max_attempts=10
    attempt=1
    while ! docker info &> /dev/null; do
        if [ $attempt -gt $max_attempts ]; then
            echo "Error: Docker daemon failed to start after $max_attempts attempts."
            echo "Please try starting it manually with: sudo systemctl start docker"
            exit 1
        fi
        echo "Attempt $attempt/$max_attempts: Docker daemon not ready yet. Waiting 2 seconds..."
        sleep 2
        attempt=$((attempt+1))
    done
    echo "Docker daemon is now running."
fi

echo "################################################################"
echo "Build folder: $buildFolder"
echo "Out folder : $outFolder"
echo "################################################################"
echo "Building in Docker - using all CPU cores"
echo "################################################################"

# Create Docker image if it doesn't exist
if ! docker image inspect "$dockerImageName" &>/dev/null; then
    echo "Creating Docker image: $dockerImageName..."
    # Create temporary Dockerfile
    cat > "$SCRIPT_DIR/Dockerfile" << EOF
FROM archlinux:latest

# Update system and install required packages
RUN pacman -Syu --noconfirm && \
    pacman -S --noconfirm archiso base-devel git sudo

# Create a build user with same UID as host user
RUN useradd -m -G wheel -u $HOST_UID builder && \
    echo '%wheel ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers

# Set up working directory
WORKDIR /build

# Keep container running for reuse
CMD ["/bin/bash"]
EOF

    # Build Docker image
    docker build -t "$dockerImageName" -f "$SCRIPT_DIR/Dockerfile" "$SCRIPT_DIR"
    
    # Remove temporary Dockerfile
    rm "$SCRIPT_DIR/Dockerfile"
fi

# Check if container exists
if docker container inspect "$dockerContainerName" &>/dev/null; then
    # Container exists, check if it's running
    if [ "$(docker container inspect -f '{{.State.Running}}' "$dockerContainerName")" != "true" ]; then
        echo "Starting existing Docker container: $dockerContainerName..."
        docker start "$dockerContainerName"
    else
        echo "Using existing running Docker container: $dockerContainerName..."
    fi
else
    # Container doesn't exist, create and start it
    echo "Creating and starting Docker container: $dockerContainerName..."
    docker run -d \
        --name "$dockerContainerName" \
        --privileged \
        --cpus="$(nproc)" \
        -v "$SCRIPT_DIR:/build" \
        "$dockerImageName" \
        tail -f /dev/null
fi

# Create required directories
mkdir -p "$buildFolder" "$outFolder"

# Run the build process inside Docker
echo "Building ISO in Docker container..."
docker exec -it "$dockerContainerName" bash -c "
    cd /build && \
    # Make mkarchiso verbose
    sudo sed -i 's/quiet=\"y\"/quiet=\"n\"/g' /usr/bin/mkarchiso && \
    # Clean build environment
    [ -d \"/build/build\" ] && sudo rm -rf \"/build/build\" && \
    mkdir -p \"/build/build\" && \
    # Copy releng folder
    cp -r \"/build/releng\" \"/build/build/\" && \
    # Copy pkgs folder (if it exists), then generate repo db
    if [ -d \"/build/pkgs\" ]; then
        cp -r \"/build/pkgs\" \"/build/build/\" && \
        echo \"Copied pkgs folder to build directory\" && \
        if ls /build/build/pkgs/*.pkg.tar.* 1>/dev/null 2>&1; then
            echo \"Generating local repository database (repo-add custom.db.tar.gz) ...\" && \
            sudo repo-add /build/build/pkgs/custom.db.tar.gz /build/build/pkgs/*.pkg.tar.* && \
            echo \"Local repo database created.\"
        else
            echo \"No .pkg.tar.* files found in pkgs. Skipping repo-add.\"
        fi
    else
        echo \"Warning: pkgs folder not found in \$SCRIPT_DIR\"
    fi && \
    # Create output directory
    mkdir -p \"/build/out\" && \
    # Build ISO
    cd \"/build/build/releng\" && \
    sudo mkarchiso -v -w \"/build/build\" -o \"/build/out\" \"\$PWD\" && \
    # Save package list
    rename=\$(date +%Y-%m-%d) && \
    if [ -f \"/build/build/iso/arch/pkglist.x86_64.txt\" ]; then
        sudo cp \"/build/build/iso/arch/pkglist.x86_64.txt\" \"/build/out/archlinux-\$rename-pkglist.txt\"
    fi && \
    # Clean build environment
    sudo rm -rf \"/build/build\" && \
    # Fix permissions on out folder
    sudo chown -R $HOST_UID:$HOST_GID \"/build/out\"
"

echo "################################################################"
echo "DONE"
echo "Check your out folder: $outFolder"
echo "################################################################"