# coding: utf-8
"""
   flask_storage.qiniu
    ~~~~~~~~~~~~~~~~~~~

    Qiniu storage, save the file to Qiniu.
"""

from __future__ import absolute_import
import os
from werkzeug import cached_property
import qiniu

from ._base import BaseStorage
from ._compat import urljoin
from ._utils import ConfigItem


class QiniuStorage(BaseStorage):

    access_key = ConfigItem('access_key', required=True)
    secret_key = ConfigItem('secret_key', required=True)

    bucket = ConfigItem('bucket', required=True)
    base_url = ConfigItem('base_url', required=True)
    base_dir = ConfigItem('base_dir')
    private = ConfigItem('private', default=False)
    expires = ConfigItem('expires', default=3600)

    def __init__(self, name, extensions, config):
        super(QiniuStorage, self).__init__(name, extensions, config)

    @cached_property
    def auth(self):
        return qiniu.Auth(self.access_key, self.secret_key)

    @cached_property
    def _client(self):
        return qiniu.BucketManager(self.auth)

    def url(self, filename):
        """Generate the url for a filename.

        :param filename: Name of the file.
        """
        base_url = urljoin(self.base_url, self.base_dir) if self.base_dir else self.base_url

        file_url = urljoin(base_url, filename)
        if self.private:
            return self.auth.private_download_url(file_url, expires=self.expires)
        return file_url

    def generate_upload_token(self, filename=None):
        """
        Generate a upload token used by client.
        :param filename: Client can upload file if filename is None.
                    Otherwise, client can modify the file.
        """
        if filename:
            token = self.auth.upload_token(self.bucket, filename)
        else:
            token = self.auth.upload_token(self.bucket)
        return token

    def save(self, storage, filename, token=None):
        self.check(storage)

        _, extname = os.path.splitext(filename)
        ext = extname.lower()[1:]
        if not self.extension_allowed(ext):
            _, extname = os.path.splitext(storage.filename)
            ext = extname.lower()[1:]
            filename = '{}.{}'.format(filename, ext) if ext else filename

        if token is None:
            token = self.generate_upload_token()
        stream = storage.stream
        ret, info = qiniu.put_data(token, filename, stream)
        if ret is None:
            raise QiniuException(info)
        return ret.get('key')

    def delete(self, filename):
        ret, info = self._client.delete(self.bucket, filename)
        if ret is None:
            raise QiniuException(info)
        return ret


class QiniuException(Exception):
    pass

@@ -589,16 +589,28 @@
 ase_dir'
+, default=''
 )%0A    pr
@@ -1036,32 +1036,47 @@
 l(self, filename
+, base_dir=None
 ):%0A        %22%22%22Ge
@@ -1174,55 +1174,40 @@
     
-base_url = urljoin(self.base_url, self.
+filename = os.path.join(
 base_dir
 ) if
@@ -1202,20 +1202,19 @@
 base_dir
-) if
+ or
  self.ba
@@ -1223,27 +1223,19 @@
 _dir
- else self.base_url
+, filename)
 %0A%0A  
@@ -1255,24 +1255,29 @@
 l = urljoin(
+self.
 base_url, fi
@@ -1883,16 +1883,36 @@
 filename
+=None, base_dir=None
 , token=
@@ -1943,24 +1943,87 @@
 k(storage)%0A%0A
+        filename = filename if filename else storage.filename%0A%0A
         _, e
@@ -2301,32 +2301,107 @@
  else filename%0A%0A
+        full_filename = os.path.join(base_dir or self.base_dir, filename)%0A%0A
         if token
@@ -2533,16 +2533,21 @@
 (token, 
+full_
 filename
@@ -2638,22 +2638,16 @@
 urn 
-ret.get('key')
+filename
 %0A%0A  
@@ -2673,18 +2673,102 @@
 filename
+, base_dir=None):%0A        filename = os.path.join(base_dir or self.base_dir, filename
 )
-:
 %0A       

add base dir support