# coding=utf-8
"""
"""
from __future__ import absolute_import

from werkzeug import secure_filename
from werkzeug.exceptions import BadRequest, NotFound
from flask import request, current_app, send_file, jsonify
from flask.signals import request_tearing_down
from flask_login import current_user

from abilian.web import csrf, url_for
from abilian.web.blueprints import Blueprint
from abilian.web.views import View, JSONView

bp = Blueprint('uploads', __name__, url_prefix='/upload')


class BaseUploadsView(object):

  def prepare_args(self, args, kwargs):
    args, kwargs = super(BaseUploadsView, self).prepare_args(args, kwargs)
    self.uploads = current_app.extensions['uploads']
    self.user = current_user._get_current_object()
    return args, kwargs

  
class NewUploadView(BaseUploadsView, JSONView):
  """
  Upload a new file
  """
  methods = ['POST', 'PUT']
  decorators = (csrf.support_graceful_failure,)

  #: file handle to be returned
  handle = None

  def data(self, *args, **kwargs):
    return {
      'handle': self.handle,
      'url': url_for('.handle', handle=self.handle),
    }
  
  def post(self, *args, **kwargs):
    if 'file' not in request.files:
      raise BadRequest('File is missing.')
    
    uploaded = request.files['file']
    filename = secure_filename(uploaded.filename)
    self.handle = self.uploads.add_file(self.user, uploaded, filename=filename)
    return self.get(*args, **kwargs)
    
  def put(self, *args, **kwargs):
    return self.post(*args, **kwargs)


bp.add_url_rule('/', view_func=NewUploadView.as_view('new_file',),)


class _StreamCloser(object):
  """
  Ensure file is closed after after response has been sent.
  """
  def __init__(self, stream):
    self.stream = stream
    request_tearing_down.connect(self, weak=False)

  def __call__(self, *args, **kwargs):
    try:
      self.stream.close()
      self.stream = None
    finally:
      request_tearing_down.disconnect(self)
      

class UploadView(BaseUploadsView, View):
  """
  Manage an uploaded file: download, delete
  """
  methods = ['GET', 'DELETE']
  decorators = (csrf.support_graceful_failure,)
  
  def get(self, handle, *args, **kwargs):
    file_obj = self.uploads.get_file(self.user, handle)

    if file_obj is None:
      raise NotFound()

    metadata = self.uploads.get_metadata(self.user, handle)
    filename = metadata.get('filename', handle)
    stream = file_obj.open('rb')
    _StreamCloser(stream)
    
    return send_file(stream,
                     as_attachment=True,
                     attachment_filename=filename,
                     cache_timeout=0,
                     add_etags=False,
                     conditional=False)

  def delete(self, handle, *args, **kwargs):
    if self.uploads.get_file(self.user, handle) is None:
      raise NotFound()

    self.uploads.remove_file(self.user, handle)
    return jsonify({'success': True})

  
bp.add_url_rule('/<string:handle>', view_func=UploadView.as_view('handle',),)

@@ -288,16 +288,68 @@
 ent_user
+%0Afrom flask_wtf.file import FileField, file_required
 %0A%0Afrom a
@@ -380,16 +380,51 @@
 url_for%0A
+from abilian.web.forms import Form%0A
 from abi
@@ -565,16 +565,92 @@
 load')%0A%0A
+class UploadForm(Form):%0A%0A  file = FileField(validators=(file_required,))%0A%0A  
 %0Aclass B
@@ -1309,38 +1309,55 @@
     
-if 'file' not in request.files
+form = UploadForm()%0A%0A    if not form.validate()
 :%0A  
@@ -1421,29 +1421,20 @@
 d = 
-request.files
+form
 %5B'file'%5D
 %0A   
@@ -1429,16 +1429,21 @@
 %5B'file'%5D
+.data
 %0A    fil

use form