"""
Title: Floppy Copy
Version: v1.1
Author: econeiric.cc
Description: A script to automatically copy/dump the 
            contents of a floppy disk when it is inserted into the drive.
"""

import os
import shutil
import time
from datetime import datetime

# --- Configuration ---
FLOPPY_DRIVE = 'A:\\' 
DEST_DIR = 'DiskCopies' # folder to save disk copies to. Each disk copy will be given a unique folder.
MAX_RETRIES = 3 # The number of times to retry copying a file
# --- End Configuration ---

def get_total_files(source_path):
    """Counts the total number of files in a directory and its subdirectories."""
    count = 0
    if not os.path.isdir(source_path):
        return 0
    for root, _, files in os.walk(source_path):
        count += len(files)
    return count

def copy_file_with_retry(source_file, dest_file, max_retries):
    """Tries to copy a file, retrying a specified number of times on failure."""
    for attempt in range(max_retries):
        try:
            # Copy the file, preserving metadata like timestamps
            shutil.copy2(source_file, dest_file)
            return True # Success
        except (IOError, OSError) as e:
            if attempt < max_retries - 1:
                # Optional: add a small delay before retrying
                time.sleep(0.1) 
            else:
                print(f"\n[ERROR] Failed to copy {source_file}: {e}")
                return False # Failed after all retries
    return False

def copy_with_progress(source, destination):
    """Copies all files from source to destination, printing progress for each file."""
    # Create the destination directory if it doesn't exist
    os.makedirs(destination, exist_ok=True)
    
    total_files = get_total_files(source)
    if total_files == 0:
        print("Floppy is empty or contains no readable files.")
        return

    print(f"Total files to copy: {total_files}")
    
    files_processed = 0
    # Walk through the source directory
    for root, dirs, files in os.walk(source):
        # Create corresponding subdirectories in the destination
        for dir_name in dirs:
            source_path = os.path.join(root, dir_name)
            dest_path = os.path.join(destination, os.path.relpath(source_path, source))
            os.makedirs(dest_path, exist_ok=True)
        
        # Copy all files
        for file_name in files:
            files_processed += 1
            source_file = os.path.join(root, file_name)
            dest_file = os.path.join(destination, os.path.relpath(source_file, source))
            
            # Get file size for progress display
            try:
                file_sizeKB = round(os.path.getsize(source_file) / 1024, 2)
            except OSError as e:
                print(f"\n[WARNING] Could not get size of {source_file}: {e}")
                file_sizeKB = 0

            # Calculate percentage
            percentage = (files_processed / total_files) * 100
            
            # Format the size string and pad it to 9 characters
            size_str = f"{file_sizeKB} KB"
            padded_size = f"{size_str:<9}"

            # Print the status line for the current file
            status = (
                f"{file_name} | {padded_size} | "
                f"File: {files_processed}/{total_files} ({percentage:.1f}%)"
            )
            print(status)

            # Attempt to copy the file
            copy_file_with_retry(source_file, dest_file, MAX_RETRIES)

    print("\nCopy complete!")

def main():
    """Main function to monitor the floppy drive and trigger the copy process."""
    while True:
        print(f"Waiting for a floppy disk to be inserted into {FLOPPY_DRIVE}")
        
        # Continuously check for the existence of the floppy drive path
        while not os.path.exists(FLOPPY_DRIVE):
            time.sleep(1)
        
        # Disk has been detected
        print("Floppy disk detected! Starting the copy process...")
        
        # Create a unique folder for the copy using a timestamp
        timestamp = datetime.now().strftime('%Y-%m-%d_%H-%M-%S')
        copy_folder = os.path.join(DEST_DIR, f'disk_copy_{timestamp}')
        
        try:
            copy_with_progress(FLOPPY_DRIVE, copy_folder)
            
            # After copying, wait for the disk to be ejected
            print("\n-----------------------------------------------------")
            print("You can now safely eject the floppy disk. <3")
            print("-----------------------------------------------------")
            
            # Wait for the drive to become unavailable again before looping
            while os.path.exists(FLOPPY_DRIVE):
                time.sleep(1)
                
        except (IOError, OSError) as e:
            print(f"An error occurred during the copy process: {e}")
            print("Please check the disk and try again.")
            
        print("\nReady for the next disk.")
        time.sleep(2) # A short pause before starting to check again

if __name__ == "__main__":
    main()
