from . import conversion, structure, custom
from .benchmark import benchmarking

def full_render(id, format, elm, pname=None, filters={}, visible_only=None):
    ret, actual = full_render_any(id, [format], elm, pname, filters, 
                                  visible_only)
    if ret is None:
        raise Exception(actual)
    return ret

def full_render_any(id, formats, elm, pname=None, filters={}, 
                    visible_only=None):
    """If 'visible_only' is not None, fail if the prop isn't visible,
    showing 'visible_only' as an error message."""
    assert id
    assert elm is not None

    filters = dict(filters)
    if pname is not None:
        pname = conversion.extract_filters(pname, filters)

    if pname is None:
        pname = u'product'

    if not elm.has_propval(pname):
        return None, "'%s' not in element '%s'." % (pname, elm.ename)

    if formats is None:
        # TODO(xavid): base it on the actual format for blob?
        formats = structure.get_flavor(pname).default_formats

    prop = structure.get_prop(pname)
    if visible_only and not prop.visible:
        return None, None

    with benchmarking('getting %s.%s' % (elm.ename, pname)):
        propval = elm.get_propval(pname)
    
    try:
        im = conversion.convert_any(elm.ename, pname, formats, filters)
        ret = im.asData()
        actual = im.getExtension()
        if im.deps.isRestricted() and not custom.is_omniscient():
            # This is generally because of some sort of markup error,
            # not normal access control.
            # Use our normal exception reporting behavior.
            raise Exception(ret)
    except conversion.ConversionFailedException,e:
        return None, e
    
    if not isinstance(ret, str):
        # TG doesn't like buffers or unicode.
        if actual in conversion.UNICODE_FORMATS:
            ret = ret.encode('utf-8')
        else:
            ret = str(ret)

    return ret, actual
