from __future__ import absolute_import, unicode_literals

import os
import re

from dcard.utils import client


reg_images    = re.compile('http[s]?://\S+\.(?:jpg|png|gif)')
reg_imgur     = re.compile('http[s]?://imgur.com/(\w+)')
reg_imgur_file = re.compile('http[s]?://i.imgur.com/\w+\.(?:jpg|png|gif)')
pattern_imgur_file = 'http://i.imgur.com/{img_hash}.jpg'



def download(task):
    src, folder = task
    filepath = '{folder_name}/{file_name}'.format(
        folder_name=folder,
        file_name=os.path.basename(src)
    )
    if os.path.exists(filepath):
        return True
    response = client.get_stream(src)
    if response.ok:
        with open(filepath, 'wb') as stream:
            for chunk in response.iter_content(chunk_size=1024):
                stream.write(chunk)
    else:
        print('%s can not download.' % src)
    return response.ok


class Downloader:

    def __init__(self, download_folder=None, subfolder_pattern=None):
        self.resources_folder = download_folder or './downloads'
        self.subfolder_pattern = subfolder_pattern or '({id}) {folder_name}'
        self.done_resources = 0

    def set_bundles(self, resource_bundles):
        self.resource_bundles = resource_bundles

    def download(self):
        tasks = []
        for bundle in self.resource_bundles:
            meta, urls = bundle
            if len(urls) == 0:
                continue
            self.done_resources += len(urls)
            folder = self.gen_full_folder(meta)
            tasks += [(url, folder) for url in urls]
            Downloader.mkdir(folder)

        results = client.parallel_tasks(download, tasks)
        return results.get()

    def gen_full_folder(self, meta):
        safe_title = re.sub('[\?\\/><:"|\*.]', '', meta['title']).strip()
        folder = self.subfolder_pattern.format(
            **meta, folder_name=safe_title
        )
        return self.resources_folder + '/' + folder

    @staticmethod
    def mkdir(path):
        if not os.path.exists(path):
            os.makedirs(path)


class ContentParser:

    def __init__(self, results, constraints):
        self.results = results
        self.constraints = constraints

    def parse(self):

        def validate(post):
            ''' crazy impl. XD '''
            if not self.constraints:
                return True

            _post = post['content']
            for key, rule in self.constraints.items():
                expression = "_post['%s']%s" % (key, rule)
                if eval(expression) is False:
                    return False
            return True

        def parse(post):
            article = post['content']
            content = article['content']
            imgur_files = ContentParser._parse_images(content)
            del article['content']
            return (article, imgur_files)

        if isinstance(self.results, dict):
            return [parse(self.results)] if validate(self.results) else []

        resoures = [parse(post) for post in self.results if validate(post)]
        return resoures

    @staticmethod
    def _parse_images(raw_data):
        imgurs = reg_imgur.findall(raw_data)
        imgur_files = reg_imgur_file.findall(raw_data)
        imgur_files += [pattern_imgur_file.format(img_hash=r) for r in imgurs]
        return imgur_files

@@ -387,151 +387,28 @@
     
-src, folder = task%0A    filepath = '%7Bfolder_name%7D/%7Bfile_name%7D'.format(%0A        folder_name=folder,%0A        file_name=os.path.basename(src)%0A    )
+filepath, src = task
 %0A   
@@ -781,16 +781,24 @@
 __(self,
+%0A       
  downloa
@@ -834,16 +834,31 @@
 ern=None
+, flatten=False
 ):%0A     
@@ -1025,16 +1025,95 @@
 rces = 0
+%0A        self.flatten = flatten%0A        Downloader.mkdir(self.resources_folder)
 %0A%0A    de
@@ -1422,24 +1422,224 @@
 n(urls)%0A    
+        tasks += %5B(self._gen_filepath(meta, url), url) for url in urls%5D%0A%0A        results = client.parallel_tasks(download, tasks)%0A        return results.get()%0A%0A    def _gen_filepath(self, meta, url):%0A
         fold
@@ -1648,16 +1648,17 @@
  = self.
+_
 gen_full
@@ -1683,90 +1683,138 @@
     
-    tasks += %5B(url, folder) for url in urls%5D%0A            Downloader.mkdir(
+base_name = os.path.basename(url)%0A        filepath = '%7Bfolder_name%7D%7Bseparator%7D%7Bfile_name%7D'.format(%0A            folder_name=
 folder
-)%0A
+,
 %0A   
@@ -1822,56 +1822,156 @@
     
-results = client.parallel_tasks(download, tasks)
+    file_name=base_name,%0A            separator='-' if self.flatten else '/'%0A        )%0A        Downloader.mkdir(folder) if not self.flatten else None
 %0A   
@@ -1978,37 +1978,32 @@
      return 
-results.get()
+filepath
 %0A%0A    def ge
@@ -2000,16 +2000,17 @@
     def 
+_
 gen_full
@@ -2116,100 +2116,96 @@
     
-folder = self.subfolder_pattern.format(%0A            **meta, folder_name=safe_title%0A        )
+meta%5B'folder_name'%5D = safe_title%0A        folder = self.subfolder_pattern.format(**meta) 
 %0A   

add flatten download subfolders switch