import sys
import hashlib, urllib

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, auth
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, *args):
        print >>sys.stderr, 'Here!'
        name = unicode(name, 'utf-8')
        if len(args) > 0:
            args = [unicode(a, 'utf-8') for a in args]
            args[-1],typ = filename_split(args[-1])
            id = args[-1]
        else:
            name,typ = filename_split(name)
            name = name.replace('_', ' ')
            name = name.replace('~:', '/')
            id = name

        if name[0] == '+':
            pname = None #maybe_pname
            elm = structure.get_element(name[1:])
            if ename_to_hash(elm.ename) != hash:
                raise HTTPNotFound((hash, name))
        else:
            if len(args) == 1:
                pname = args[0]
            else:
                assert len(args) == 0, args
                pname = None
            args = []
            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'):
            owner = auth.user_by_username(username)
            assert owner is not None, username
            filters['let'][u'owner'] = owner.ename
        if args:
            for i in xrange(len(args)):
                filters['let'][unicode(i + 1)] = args[i]
        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)
            # TODO(xavid): TurboGears still doesn't handle /s right, because
            #              dumb. Ideally, these'd get urlencoded, the args below
            #              wouldn't, and it'll all be fine.
            name = name.replace('/', '~:')
        else:
            # TODO(xavid): Should be encoded in some way.
            # TODO(xavid): Handle name starting with +
            name = u"+%s/%s" % (element.ename, '/'.join(args))
        name = urllib.quote(name.encode('utf-8'), '+/')
        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')
                if owner.has_propval(u'username'):
                    username = render(owner, u'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)
