# This file is part of Rubber and thus covered by the GPL
# (c) Sebastian Reichel, 2014
"""
basic BibLaTeX support for Rubber
"""

import sys
from os import getenv
from os.path import join, exists, getmtime
from rubber.util import parse_keyval, md5_file
from rubber import _, msg
from string import split

def setup (document, context):
    global doc
    doc = document

    opt = context['opt'] or None
    options = parse_keyval(opt) if opt != None else {}
    
    if "backend" in options and options["backend"] != "biber":
        msg.warn(_("rubber's biblatex plugin only supports the biber backend"))

    doc.hook_macro('addbibresource', 'oa', hook_bibresource)
    doc.hook_macro('addglobalbib', 'oa', hook_bibresource)
    doc.hook_macro('addsectionbib', 'oa', hook_bibresource)
    doc.hook_macro('bibliography', 'a', hook_bibliography)

    get_initial_hashes()

def get_initial_hashes ():
    global bcfhash
    global bblhash

    bcfhash = None

    bbl = doc.target + "." + "bbl"
    if exists(bbl):
        bblhash = md5_file(bbl)
    else:
        bblhash = None

def hook_bibresource (loc, opt, file):
    options = parse_keyval(opt) if opt != None else {}

    # If the file name looks like it contains a control sequence
    # or a macro argument, forget about this resource.
    if file.find('\\') > 0 or file.find('#') > 0:
        return

    # skip remote resources
    if 'location' in options and options['location'] == 'remote':
        return

    # BIBINPUTS support with fallback to current working directory
    bibinputs = getenv("BIBINPUTS", ".")
    for bibpath in bibinputs.split(":"):
        bibfile = join(bibpath, file)
        if exists(bibfile):
            doc.add_source(bibfile)
            return

    msg.error(_("cannot find %s") % file)
    sys.exit(2)

def hook_bibliography (loc, files):
    for bib in split(files, ","):
        hook_bibresource(loc, None, bib.strip()+".bib")

def biber_needed():
    bcf = doc.target + "." + "bcf"
    bbl = doc.target + "." + "bbl"
    if not exists(bcf):
        msg.info(_("bcf file has not been generated by biblatex!"))
        return False
    if not exists(bbl):
        return True
    if getmtime(bbl) > getmtime(bcf):
        return False
    if bcfhash == md5_file(bcf):
        return False
    return True

def run_biber():
    global bcfhash
    global bblhash
    bcf = doc.target + "." + "bcf"
    bbl = doc.target + "." + "bbl"
    msg.progress(_("running biber on %s") % msg.simplify(bcf));
    if doc.env.execute(["biber", bcf]):
        msg.info(_("There were errors making the bibliography."))
        return False
    bcfhash = md5_file(bcf)
    newbblhash = md5_file(bbl)
    if bblhash != newbblhash:
        bblhash = newbblhash
        doc.must_compile = 1
    else:
        msg.info(_("bbl file styed the same, no recompilation needed."))
    return True

def post_compile ():
    if not biber_needed():
        return True
    return run_biber()

def clean ():
    # generated by the biblatex module
    doc.remove_suffixes([".run.xml", ".bcf"])
    # generated by biber
    doc.remove_suffixes([".bbl", ".blg"])
