# -*- coding: utf-8 -*-
from __future__ import unicode_literals, absolute_import

from celery import shared_task, chain
from os import system, path, makedirs, rename
join = path.join
from shutil import rmtree, move
from urllib2 import urlopen
from contextlib import closing
import subprocess


from www import settings 
from documents.models import Document, Page

def document_pdir(document):
    return join(settings.PROCESSING_DIR,"doc-{}".format(document.id))
    

@shared_task(bind=True)
def download(self, document_id):
    document = Document.objects.get(pk=document_id)
    tmp_path = document_pdir(document)

    # Delete some old tries if any
    if path.exists(tmp_path):
        rmtree(tmp_path)

    makedirs(tmp_path)
    document.type = 'pdf'
    destination_name = join(tmp_path,"{}.{}".format(document_id,document.type))

    with closing(urlopen(document.source)) as original:
        with open(destination_name, 'w') as destination:
            destination.write(original.read())

    document.staticfile = destination_name
    document.save()

    try: # may fail if download url, don't really care
        system("rm /tmp/TMP402_%d.pdf" % pending.document.id)
    except:
        pass

    return document_id 


@shared_task(bind=True)
def calculate_pdf_length(self, document_id):
    document = Document.objects.get(pk=document_id)

    sub = subprocess.check_output(['gm', 'identify', document.staticfile])
    pages = len(sub.split('\n')) - 1

    document.pages = pages
    document.save()

    return document_id 

@shared_task(bind=True)
def index_pdf(self, document_id):
    document = Document.objects.get(pk=document_id)

    system("pdftotext " + filename)
    # change extension
    words_file = '.'.join(document.staticfile.split('.')[:-1]) + ".txt"

    with open(words_file, 'r') as words:
        # Do a lot of cool things !
        pass

    return document_id 

@shared_task(bind=True)
def preview_pdf(self, document_id):
    document = Document.objects.get(pk=document_id)
    source = document.staticfile

    destination_dir = join(document_pdir(document), "images")
    if not path.exists(destination_dir):
        makedirs(destination_dir)

    for pagenum in range(document.pages):
        heights = {}

        for width, size_name in [(120, 'm'), (600, 'n'), (900, 'b')]:
            destination = join(destination_dir, "{:0>6}_{}.jpg".format(pagenum, size_name))
            args = (width, ' -density 350', source, pagenum, destination)

            system('gm convert -geometry %dx -quality 90 %s "%s[%d]" %s' % args)

            height = int(subprocess.check_output(['gm', 'identify', '-format', '%h', destination]).strip())
            heights["height_{}".format(width)] = height

        page = Page.objects.create(numero=pagenum, **heights)
        document.add_child(page, acyclic_check=False)

    return document_id 

@shared_task(bind=True)
def finish_file(self, document_id):
    document = Document.objects.get(pk=document_id)
    tmp_path = document_pdir(document)

    destination = join(settings.UPLOAD_DIR, str(document.parent.id))

    if not path.exists(destination):
        makedirs(destination)

    move(tmp_path, destination)

    document.state = 'done'
    document.save()

    return document_id 

process_pdf = chain(download.s(), calculate_pdf_length.s(), preview_pdf.s(), finish_file.s())

@@ -358,16 +358,66 @@
 , Page%0A%0A
+class MissingBinary(EnvironmentError):%0A    pass%0A%0A%0A
 def docu
@@ -1395,24 +1395,37 @@
 cument_id)%0A%0A
+    try:%0A    
     sub = su
@@ -1487,16 +1487,196 @@
 cfile%5D)%0A
+    except OSError:%0A        raise MissingBinary(%22gm%22)%0A    except subprocess.CalledProcessError:%0A        print %22'gm identify %22 + document.staticfile + %22' has failed%22%0A        raise%0A%0A
     page
@@ -1885,24 +1885,266 @@
 cument_id)%0A%0A
+    try:%0A        subprocess.check_output(%5B'pdftotext', '-v'%5D)%0A    except OSError:%0A        raise MissingBinary(%22pdftotext%22)%0A    except:%0A        print %22Unknown error while testing pdftotext presence%22%0A        raise%0A%0A    # TODO : this could fail%0A
     system(%22
@@ -2263,16 +2263,45 @@
 %22.txt%22%0A%0A
+    # TODO : this could fail%0A
     with
@@ -2460,32 +2460,226 @@
 , document_id):%0A
+    try:%0A        subprocess.check_output(%5B'gm', 'help'%5D)%0A    except OSError:%0A        raise MissingBinary(%22gm%22)%0A    except:%0A        print %22Unknown error while testing gm presence%22%0A        raise%0A%0A
     document = D
@@ -3285,21 +3285,38 @@
     
-height = int(
+try:%0A                output = 
 subp
@@ -3384,16 +3384,308 @@
 nation%5D)
+%0A            except OSError:%0A                raise MissingBinary(%22gm%22)%0A            except subprocess.CalledProcessError:%0A                # Command has failed%0A                print %22'gm identify -format %25h %22 + destination + %22' has failed%22%0A                raise%0A%0A            height = int(output
 .strip()

Add more security the processing chain (verify missing binaries, ...)