import os
import hashlib
import subprocess as sp

def find_subclasses(base_cls):
    cls_list = [base_cls]
    while cls_list:
        cls = cls_list.pop()
        cls_list.extend(cls.__subclasses__())
        if cls is base_cls:
            continue
        if cls.__dict__.get("__abstract__"):
            continue
        yield cls

def get_exif(path):
    return dict(_iter_exif(path))

def _iter_exif(path):
    exiftool_bin = os.environ.get("EXIFTOOL_CMD", "exiftool")
    proc = sp.Popen(
        [exiftool_bin, path],
        stdout=sp.PIPE, stderr=sp.PIPE
    )
    stdout, stderr = proc.communicate()
    for line in stdout.splitlines():
        key, _, val = line.strip().partition(":")
        key = key.strip().lower().replace(" ", "-")
        val = val.strip()
        if key and val:
            yield (key, val)

def get_file_sha1(f):
    hash = hashlib.sha1()
    for chunk in iter(lambda: f.read(4096), ""):
        hash.update(chunk)
    return hash.hexdigest()

def mkdir(dir):
    if not os.path.exists(dir):
        os.mkdir(dir)

def unsafe_gs_get_page_count(file):
    # Note: this is unsafe because I have no idea whether this escaping is
    # safe or correct.
    file_escaped = (
        file
            .replace("(", "\\(")
            .replace(")", "\\)")
            .replace("\\", "\\\\")
    )
    gs_bin = os.environ.get("GS_CMD", "gs")
    proc = sp.Popen([
        gs_bin, "-q", "-dNODISPLAY", "-c",
        "(%s) (r) file runpdfbegin pdfpagecount = quit" %(file_escaped, )
    ], stdout=sp.PIPE, stderr=sp.PIPE)
    stdout, _ = proc.communicate()
    return stdout
