import wsgiref.handlers
from django.utils import simplejson
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
from google.appengine.api import urlfetch
from models import Bin, Post
import urllib
import re
import hashlib
from cgi import FieldStorage
import logging
from google.appengine.api.labs import taskqueue

class NotFound(Exception): pass


class BinHandler(webapp.RequestHandler):
    def get(self):
        path = self.request.path
        if path[-1] == '/':
            self.redirect(path[:-1])
        path, feed = re.subn(r'^(.+)\/feed$', r'\1', path)
        bin = self._get_bin(path)
        if self.request.query_string:
            self._record_post(bin, True)
            self.redirect('/%s' % bin.name)
        else:
            posts = bin.post_set.order('-created').fetch(50)
            self.response.out.write(template.render('templates/bin.%s' % ('atom' if feed else 'html'), 
                {'bin':bin, 'posts':posts, 'request':self.request}))

    def post(self):
        bin = self._get_bin(self.request.path)
        post = self._record_post(bin)
        # TODO: This should maybe be a header thing
        if 'http://' in self.request.query_string:
            params = dict(self.request.POST.items())
            params['_url'] = self.request.query_string
            urlfetch.fetch(url='http://hookah.progrium.com/dispatch',
                            payload=urllib.urlencode(params), method='POST')
        taskqueue.add(url='/tasks/newpost', params={'ip': post.remote_addr, 'size': post.size, 'bin': bin.name})
        self.response.set_status(201)
        self.response.headers['Location'] = str("/%s" % bin.name)
        self.response.out.write('<html><head><meta http-equiv="refresh" content="0;url=/%s" /></head><body>201 Created. Redirecting...</body></html>' % bin.name)
    
    def head(self):
        bin = self._get_bin(self.request.path)
        if self.request.query_string:
            self._record_post(bin, True)
        else:
            self._record_post(bin)

    def handle_exception(self, exception, debug_mode):
        if isinstance(exception, NotFound):
            self.error(404)
        else:
            super(BinHandler, self).handle_exception(exception, debug_mode)

    def _record_post(self, bin, use_get=False):
        post = Post(bin=bin, remote_addr=self.request.remote_addr)
        post.headers        = dict(self.request.headers)
        try:
            post.body           = self.request.body
        except UnicodeDecodeError:
            #post.body_binary    = self.request.body
            pass
        post.query_string   = self.request.query_string
        post.form_data = []
        data_source = self.request.GET if use_get else self.request.POST
        post.size = len(post.body) if post.body else 0
        for k,v in data_source.items():
            if isinstance(v, FieldStorage):
                file_body = v.file.read()
                post.form_data.append([k, {
                    'file_name': v.filename,
                    'file_extension': v.filename.split('.')[-1],
                    'file_digest': hashlib.md5(file_body).hexdigest(),
                    'file_size': round(len(file_body) / 1024.0, 1),
                }])
                post.size += len(file_body)
            else:
                post.form_data.append([k,v])
        post.put()
        return post

    def _get_bin(self, path):
        name = path[1:].split('/')[0]
        bin = Bin.all().filter('name =', name).get()
        if bin:
            return bin
        else:
            raise NotFound()



if __name__ == '__main__':
    wsgiref.handlers.CGIHandler().run(webapp.WSGIApplication([
        ('/.*', BinHandler),
        ], debug=True))