#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os, errno
import re
import sys
import time
import datetime
import gzip
import glob

import Image, ExifTags
from ExifTags import TAGS

from optparse import make_option
from django.core.management.base import BaseCommand, CommandError
from django.template import Context, Template
from django.conf import settings as conf
import rgallery.models as mymodels
from datetime import datetime
from pprint import pprint

from sorl.thumbnail import get_thumbnail
from dropbox import client, rest, session


def get_exif(fn):
    """
    data = get_exif('img/2013-04-13 12.17.09.jpg')
    print data
    """
    ret = {}
    print fn
    i = Image.open(fn)
    info = i._getexif()
    try:
        for tag, value in info.items():
            decoded = TAGS.get(tag, tag)
            ret[decoded] = value
    except:
        now = datetime.now()
        ret['DateTimeOriginal'] = now.strftime("%Y:%m:%d %H:%M:%S")

    try:
        str(ret['DateTimeOriginal'])
    except:
        now = datetime.now()
        ret['DateTimeOriginal'] = now.strftime("%Y:%m:%d %H:%M:%S")

    return ret


def mkdir_p(path):
    try:
        os.makedirs(path)
    except OSError as exc: # Python >2.5
        if exc.errno == errno.EEXIST and os.path.isdir(path):
            pass
        else: raise

# Class MUST be named 'Command'
class Command(BaseCommand):

    # Displayed from 'manage.py help mycommand'
    help = """
    Tool that tries to download and parse photos from a Dropbox shared folder,
    saving it on the database and converting the photos to fit the web:

    ./manage.py dropbox_photosync

    1.- First time it connects with Dropbox and stores the token information in
        a token_file
    2.- Next times it read the token from file to connect Dropbox
    3.- Go to the shared folder and check if the image is already on database
    4.- If not, this script download the image, converting it to fit the web and
        save a record in the database.

    To run this script from a crontab task we should do something like this:

    */30 * * * * cd /path/to/rgallery-project/ ; source env/bin/activate ; cd src ; python manage.py dropbox_photosync > /dev/null

    """

    def handle(self, *app_labels, **options):
        """
        The command itself
        """
        # Get your app key and secret from the Dropbox developer website
        APP_KEY = conf.DROPBOX_APP_KEY
        APP_SECRET = conf.DROPBOX_APP_SECRET

        # ACCESS_TYPE should be 'dropbox' or 'app_folder' as configured for your app
        try:
            ACCESS_TYPE = conf.DROPBOX_ACCESS_TYPE
        except:
            ACCESS_TYPE = 'dropbox'

        # Creating dirs
        dropboxdir = os.path.join(conf.PROJECT_DIR, 'media', 'uploads', 'dropbox')
        destdir = os.path.join(conf.PROJECT_DIR, 'media', 'uploads', 'photos')
        if os.path.exists(dropboxdir) == False:
            mkdir_p(dropboxdir)
        if os.path.exists(destdir) == False:
            mkdir_p(destdir)

        # First time
        TOKENS = os.path.join(conf.PROJECT_DIR, 'media', 'uploads', 'dropbox', 'dropbox_token.txt')
        if not os.path.exists(TOKENS):
            sess = session.DropboxSession(APP_KEY, APP_SECRET, ACCESS_TYPE)
            request_token = sess.obtain_request_token()
            url = sess.build_authorize_url(request_token)

            # Make the user sign in and authorize this token
            print "url:", url
            print "Please visit this website and press the 'Allow' button, then hit 'Enter' here."
            raw_input()

            # This will fail if the user didn't visit the above URL
            access_token = sess.obtain_access_token(request_token)

            token_file = open(TOKENS,'w')
            token_file.write("%s|%s" % (access_token.key,access_token.secret) )
            token_file.close()
        else:
            token_file = open(TOKENS)
            token_key,token_secret = token_file.read().split('|')
            token_file.close()
            sess = session.DropboxSession(APP_KEY,APP_SECRET, ACCESS_TYPE )
            sess.set_token(token_key,token_secret)

        c = client.DropboxClient(sess)

        #print "linked account:", c.account_info()

        repetidas = 0
        descargadas = 0
        total = 0
        size = 1000, 1000

        # DROPBOX_PATH: If the access is 'dropbox' you have to specify the folder
        # If it's 'app_folder' it's ok with /
        try:
            DROPBOX_PATH = conf.DROPBOX_ACCESS_PATH
        except:
            DROPBOX_PATH = '/'

        folder_metadata = c.metadata(DROPBOX_PATH)
        #print "*"*80
        #print "metadata:", folder_metadata
        #print "*"*80
        #print "contents:", folder_metadata['contents']

        print "-"*80
        for cont in folder_metadata['contents']:
            print cont

        for cont in folder_metadata['contents']:
            try:
                str(cont['mime_type'])
            except:
                cont['mime_type'] = ''

            if cont['mime_type'] == 'image/jpeg':
                origen_name = os.path.basename(cont['path'])
                #print "origen_name=%s" % origen_name
                try:
                    im = mymodels.Photo.objects.get(origen=os.path.basename(cont['path']))
                    repetidas += 1
                    print "[***] Repetida: %s" % os.path.basename(cont['path'])
                except:
                    print "[***] La imagen %s No esta en bd, descargar y agregar a bbdd y hacer thumb" % os.path.basename(cont['path'])
                    nombre_imagen = str(cont['path']).replace('/', '').replace(' ','_').replace(':','-')

                    # Descargar
                    f, metadata = c.get_file_and_metadata(cont['path'])
                    out = open(dropboxdir + '/' + nombre_imagen, 'wb')
                    out.write(f.read())
                    out.close()
                    print "      Descargada"

                    # Meter
                    data_image = get_exif(dropboxdir + '/' + nombre_imagen)
                    capture_data = datetime.strptime(str(data_image['DateTimeOriginal']), "%Y:%m:%d %H:%M:%S")
                    im = mymodels.Photo(image="uploads/photos/" + nombre_imagen, origen=os.path.basename(cont['path']), insert_date=datetime.now(), capture_date=capture_data, status=True)
                    im.save()
                    print "      Agregada a bbdd"
                    im2 = Image.open(dropboxdir + '/' + nombre_imagen)

                    try:
                        # Rotar si es necesario
                        for orientation in ExifTags.TAGS.keys() :
                            if ExifTags.TAGS[orientation]=='Orientation' : break
                        exif=dict(im2._getexif().items())
                        if exif[orientation] == 3 :
                            im2=im2.rotate(180, expand=True)
                        elif exif[orientation] == 6 :
                            im2=im2.rotate(270, expand=True)
                        elif exif[orientation] == 8 :
                            im2=im2.rotate(90, expand=True)
                    except:
                        pass

                    im2.thumbnail(size, Image.ANTIALIAS)
                    if os.path.exists(destdir + '/' + nombre_imagen) == False:
                        im2.save(destdir + '/' + nombre_imagen)
                        print "      Thumbnail en: %s/%s" % (destdir, nombre_imagen)
                    else:
                        descargadas += 1
                        nombre_imagen_repe = str(cont['path']).replace('/','').replace(' ','_').replace(':','-').replace('.jpg','') + '_1.jpg'
                        im.image = "uploads/photos/" + nombre_imagen_repe
                        im.save()
                        im2.save(destdir + '/' + nombre_imagen_repe)
                        print "      Duplicada en disco, cambiado nombre a: %s" % nombre_imagen_repe

                    print "Haciendo thumb 200x200"
                    im = get_thumbnail(im, "200x200")
                    if im.width > 750 and im.height > 750:
                        print "Haciendo thumb 750x750"
                        im = get_thumbnail(im, "750x750")
                total += 1
            #print "-"*80

        #print "*"*80

        print "[*** Resumen ***]"
        print "[***] Repetidas en db: %s" % repetidas
        print "[***] Repetidas en disco: %s" % descargadas
        print "[***] Total: %s" % total

        print "[***] Haciendo thumbs (200x200 y 750x750) de las que no tienen todavía"
        conf.THUMBNAIL_DEBUG = True
        allphotos = mymodels.Photo.objects.all()
        for i,p in enumerate(allphotos):
            print "%s - %s" % (i, p)
            c = Context({'image': p})
            t = Template('{% load thumbnail %}{% thumbnail image "200x200" crop="top" as img %}{{ img.url }}{% endthumbnail %}')
            t.render(c)
            im = get_thumbnail(p, "200x200")
            if p.image.width > 750 and p.image.height > 750:
                im = get_thumbnail(p, "750x750")
        print "[***] Hecho."

