import sys
import hashlib

import tg, pylons
from webob.exc import HTTPNotFound

from bazbase import conversion, structure
from bazbase.wiki import (get_overridden_element, recursive_get,
                          NoContentException)
from bazki import translators
from bazki.getting import (BaseGetter, get, filename_split, 
                           DEFAULT_DEFAULT, type_to_suffix)
from gameki import restricted

def ename_to_hash(ename):
    return hashlib.md5(ename).hexdigest()[:8]

class ProdGetter(BaseGetter):
    @tg.expose()
    def _default(self, hash, username, name, pname_or_arg=None,
                 maybe_pname=None):
        print >>sys.stderr, 'Here!'
        name = unicode(name, 'utf-8')
        if maybe_pname is not None:
            maybe_pname,typ = filename_split(unicode(maybe_pname, 'utf-8'))
            id = maybe_pname
        elif pname_or_arg is not None:
            pname_or_arg,typ = filename_split(unicode(pname_or_arg, 'utf-8'))
            id = pname_or_arg
        else:
            name,typ = filename_split(name)
            name = name.replace('_', ' ')
            id = name

        if name[0] == '+':
            pname = maybe_pname
            arg = pname_or_arg.encode('utf-8')
            elm = structure.get_element(name[1:])
            if ename_to_hash(elm.ename) != hash:
                raise HTTPNotFound((hash, name))
        else:
            pname = pname_or_arg
            arg = None
            for p in structure.search_elements({u'name': name}):
                if ename_to_hash(p.ename) == hash:
                    elm = p
                    break
                else:
                    print >>sys.stderr, 'hash mismatch', ename_to_hash(p.ename), hash
            else:
                print >>sys.stderr, 'zoip'
                raise HTTPNotFound((hash, name))

        # Check access control
        visible_only = restricted.OMNISCIENT_ONLY
        logged_in = restricted.logged_in_user()
        if restricted.is_omniscient():
            # We're good.
            visible_only = None
        elif logged_in is None:
            print >>sys.stderr, 'li'
            raise restricted.log_in()
        elif username != conversion.render(logged_in, u'username'):
            print >>sys.stderr, 'ny'
            raise restricted.not_you()
        else:
            # The usernames match, but does this character have access to
            # this thing?
            # Specifically, is it in their stuff, excluding stuff that's
            # folded or owned by folded things?
            if elm in recursive_get(logged_in, u'stuff', 'exclude',
                                    folded=False):
                pass
            else:
                print >>sys.stderr, 'oo'
                raise restricted.omniscient_only()

        filters = {'metadata':
                   {'pdfurl': tg.url('/prod/%s/%s/%s.pdf'
                                     % (hash, username,
                                        '%s/%s' % (name, pname) if pname
                                        else name))},
                  'let': {}}
        # Only set owner if the element being produced is owned.
        if username != '_' and conversion.to_python(elm, u'owned'):
            filters['let'][u'owner'] = structure.get_element_raw(
                username=username)
        if arg is not None:
            filters['let'][u'1'] = arg
        print >>sys.stderr, 'preget'
        return get(id, typ, elm, pname, filters, visible_only=visible_only)

    def get_url_for(self, element, dep, render, type=None,
                    prefixtype='', args=None):
        if args is None:
            if dep:
                dep.addDep(element[u'name'])
            name = render(element, u'name')
            if not name:
                raise KeyError("%s has an empty name!" % element.ename)
        else:
            # TODO(xavid): Should be encoded in some way.
            # TODO(xavid): Handle name starting with +
            name = u"+%s/%s" % (element.ename, '/'.join(args))
        if type is False:
            typesuffix = ''
        elif type is not None:
            typesuffix = type_to_suffix(type)
            if typesuffix == DEFAULT_DEFAULT and '.' not in name:
                typesuffix = ''
        else:
            if '.' in name:
                typesuffix = DEFAULT_DEFAULT
            else:
                typesuffix = ''
        username = '_'

        #if u'owner' in let:
        #    owner = let[u'owner']
        #else:
        if True:
            owner = get_overridden_element(u'owner')
        if owner is not None:
            if element != owner:
                if dep:
                    dep.addPropvalDep(owner, u'username')
                username = render(owner, u'username') or username
        return translators.absolute_url(self.get_path
                                        + '/' + ename_to_hash(element.ename)
                                        + '/' + username
                                        + '/' + name + typesuffix, dep,
                                        prefixtype=prefixtype,
                                        render=render)

    def has_get_url(self, element, dep=None, render=conversion.render):
        if dep:
            dep.addPropvalDep(element, u'name')
            dep.addPropvalDep(element, u'product')
        try:
            return (render(element, u'name')
                    and element.has_propval(u'product'))
        except KeyError:
            return False
        except NoContentException:
            return False
    
    def attachment_url_for(self, element, pname, dep, render, type,
                           prefixtype=''):
        endbit = '/' + pname + type_to_suffix(type)
        #if self.has_get_url(element,dep,render):
        try:
            return (self.get_url_for(element,dep,render,
                                     type=False, prefixtype=prefixtype)
                    + endbit)
        except KeyError:
            return BaseGetter.attachment_url_for(self, element, pname, dep,
                                                 render, type,
                                                 prefixtype=prefixtype)
