"""Checksum Utilities

Small convenience functions to work with checksums.
"""
import hashlib
import os

from .types import PathLike


# How many bytes to read in one go. Taken from coreutils/gnulib
BLOCKSIZE = 32768


def hexdigest_file(path: PathLike, algorithm: str) -> str:
    """Return the hexdigest of the file at `path` using `algorithm`

    Will stream the contents of file to the hash `algorithm` and
    return the hexdigest. If the specified `algorithm` is not
    supported a `ValueError` will be raised.
    """
    hasher = hashlib.new(algorithm)

    with open(path, "rb") as f:

        os.posix_fadvise(f.fileno(), 0, 0, os.POSIX_FADV_SEQUENTIAL)

        while True:
            data = f.read(BLOCKSIZE)
            if not data:
                break

            hasher.update(data)

    return hasher.hexdigest()


def verify_file(path: PathLike, checksum: str) -> bool:
    """Hash the file and return if the specified `checksum` matches

    Uses `hexdigest_file` to hash the contents of the file at
    `path` and return if the hexdigest matches the one specified
    in `checksum`, where `checksum` consist of the algorithm used
    and the digest joined via `:`, e.g. `sha256:abcd...`.
    """
    algorithm, want = checksum.split(":", 1)

    have = hexdigest_file(path, algorithm)

    return have == want
