#!/usr/bin/python3

# requires imagemagick, avifenc, svt-av1

import os
import subprocess
import concurrent.futures

# below this threshold, it won't be compressed with avif
MIN_FILE_SIZE = 30000

def detect_compressible(fpath):
    mimetype = subprocess.check_output(["file", "--mime-type", "-b", fpath]).strip().decode('utf-8')

    if mimetype in ('image/png', 'image/jpeg'):
        return True

    if mimetype == 'image/webp':
        fileout = subprocess.check_output(["file", fpath]).decode('utf-8')
        if 'lossless' in fileout:
            return True

    return False

def compress(fpath):
    rtpath = '/tmp/'+os.urandom(4).hex()+'.png'
    subprocess.run(["magick", fpath, rtpath])
    subprocess.run(["avifenc", rtpath, "--yuv", "420", "--range", "l", "-q", "50", "-c", "svt", "-j", "1", "--speed", "0", "--ignore-exif", "-o", fpath])
    try:
        os.remove(rtpath)
    except:
        pass

def process_files_in_directory(directory):
    compressible_files = []

    for root, _, files in os.walk(directory):
        for fi in files:
            full_path = os.path.join(root, fi)
            print(f"Checking file: {full_path}")
            if os.path.getsize(full_path) < MIN_FILE_SIZE:
                continue
            if detect_compressible(full_path):
                compressible_files.append(full_path)

    return compressible_files

def main(directory, max_workers):
    compressible_files = process_files_in_directory(directory)

    with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
        futures = {executor.submit(compress, fpath): fpath for fpath in compressible_files}

        for future in concurrent.futures.as_completed(futures):
            fpath = futures[future]
            try:
                future.result()
                print(f"Successfully compressed: {fpath}")
            except Exception as exc:
                print(f"Compression failed for {fpath}: {exc}")

if __name__ == "__main__":
    main('../docs/', max_workers=32)
