#!/usr/bin/env python3

import subprocess
import json
from collections.abc import Generator
from pathlib import Path
from concurrent.futures import ThreadPoolExecutor


def update():
    subprocess.run(["git", "pull"], cwd=Path.home().joinpath("micropython"))


def compile(board: Path, variant:str|None=None):
    board = board.name
    cmd = f"""
        source ~/esp-idf/export.sh
        make -C ~/micropython/ports/esp32 BOARD={board} BOARD_VARIANT={variant or ""} submodules
        make -C ~/micropython/ports/esp32 BOARD={board} BOARD_VARIANT={variant or ""} -j 4
    """
    proc = subprocess.run("/bin/bash", input=cmd, encoding="utf8", stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL)


def get_boards() -> Generator[Path, None, None]:
    def order(path: Path) -> int:
        values = list(map(ord, path.name))
        if path.name.startswith("ESP32"):
            values[0] -= 100
        return values

    iterator = Path.home().joinpath("micropython/ports/esp32/boards").iterdir()
    for board in sorted(iterator, key=order):
        if board.is_dir() and board.name.isupper():
            yield board


def get_variants(board: Path) -> list[str]:
    with board.joinpath("board.json").open() as fd:
        variants = json.load(fd).get("variants", {})
        variants.pop("IDF3", None)
        return list(variants)

tasks = []

for board in get_boards():
    # print(f"Compiling board {board.name}")
    tasks.append((board, None))

    for variant in get_variants(board):
        # print(f"Compiling board {board.name} with {variant}")
        tasks.append((board, variant))

def compile_star(task: tuple[Path, str|None]):
    board, variant = task

    if variant is None:
        print(f"Compiling board {board.name}")
    else:
        print(f"Compiling board {board.name} with {variant}")

    compile(board, variant)


update()
with ThreadPoolExecutor(10) as pool:
    for task in pool.map(compile_star, tasks):
        pass


# compile("ESP32_GENERIC")

