#!/usr/bin/env python

import datetime
# import os for file system functions
import os
# import json
import json
# import regex
import re
# for date parsing
import time
# import flickrapi
# `easy_install flickrapi` or `pip install flickrapi`
import flickrapi

# main program
def fetch(api_key, api_secret):

  # create an unauthenticated flickrapi object
  flickr=flickrapi.FlickrAPI(api_key, api_secret)

  print "Open the following URL in your browser "
  print "This Url >>>> %s" % flickr.web_login_url(perms='read')

  print "When you're ready press ENTER",
  raw_input()

  print "Copy and paste the URL (from theopenphotoproject.org) here: ",
  frob_url = raw_input()

  print "\nThanks!"

  print "Parsing URL for the token...",
  match = re.search('frob=([^&]+)', frob_url)
  frob = match.group(1)
  token = flickr.get_token(frob)
  print "OK"

  # create an authenticated flickrapi object
  flickr = flickrapi.FlickrAPI(api_key, api_secret, token=token)

  # now we get the authenticated user's id
  print "Fetching user id...",
  user_resp = flickr.urls_getUserProfile()
  user_fields = user_resp.findall('user')[0]
  user_id = user_fields.get('nsid')
  print "OK"
  

# print "Enter your token: ",
# token = raw_input()
  per_page = 100

  (token, frob) = flickr.get_token_part_one('read')
  flickr.get_token_part_two((token, frob))

  # we'll paginate through the results
  # start at `page` and get `per_page` results at a time
  page=1

  # store everything in a list or array or whatever python calls this
  photos_out=[]

  # while True loop till we get no photos back
  while True:
    # call the photos.search API
    # http://www.flickr.com/services/api/flickr.photos.search.html
    print "Fetching page %d..." % page,
    photos_resp = flickr.people_getPhotos(user_id=user_id, per_page=per_page, page=page, extras='original_format,tags,geo,url_o,url_b,url_c,url_z,date_upload,date_taken,license,description')
    print "OK"

    # increment the page number before we forget so we don't endlessly loop
    page = page+1;

    # grab the first and only 'photos' node
    photo_list = photos_resp.findall('photos')[0]

    # if the list of photos is empty we must have reached the end of this user's library and break out of the while True
    if len(photo_list) == 0:
      break;

    # else we loop through the photos
    for photo in photo_list:
      # get all the data we can
      p = {}
      p['id'] = photo.get('id')
      p['permission'] = bool(int(photo.get('ispublic')))
      p['title'] = photo.get('title')
      p['license'] = getLicense(photo.get('license'))
      description = photo.findall('description')[0].text
      if description is not None:
        p['description'] = description

      if photo.get('latitude') != '0':
        p['latitude'] = float(photo.get('latitude'))

      if photo.get('longitude') != '0':
        p['longitude'] = float(photo.get('longitude'))

      if len(photo.get('tags')) > 0:
        p['tags'] = photo.get('tags').split(' ')
      else:
        p['tags'] = []
      if photo.get('place_id') is not None:
        p['tags'].append("flickr:place_id=%s" % photo.get('place_id'))

      if photo.get('woe_id') is not None:
        p['tags'].append("geo:woe_id=%s" % photo.get('woe_id'))

      p['tags'] = ",".join(p['tags'])
      p['dateUploaded'] = int(photo.get('dateupload'))
      p['dateTaken'] = int(time.mktime(time.strptime(photo.get('datetaken'), '%Y-%m-%d %H:%M:%S')))

      # Attention : this is returned only for Pro accounts, it seems
      if photo.get('url_o') is not None:
        p['photo'] = photo.get('url_o')
      elif photo.get('url_b') is not None:
        p['photo'] = photo.get('url_b')
      elif photo.get('url_c') is not None:
        p['photo'] = photo.get('url_c')
      elif photo.get('url_z') is not None:
        p['photo'] = photo.get('url_z')

      t = datetime.datetime.fromtimestamp(float(p['dateUploaded']))
      filename = '%s-%s' % (t.strftime('%Y%m%dT%H%M%S'), p['id'])

      print "  * Storing photo %s to fetched/%s.json" % (p['id'], filename),
      f = open("fetched/%s.json" % filename, 'w')
      f.write(json.dumps(p))
      f.close()
      print "OK"

# create a directory only if it doesn't already exist
def createDirectorySafe( name ):
  if not os.path.exists(name):
    os.makedirs(name)

# construct the url for the original photo
# currently this requires a pro account
def constructUrl( photo ):
  return "http://farm%s.staticflickr.com/%s/%s_%s_o.%s" % (photo.get('farm'), photo.get('server'), photo.get('id'), photo.get('originalsecret'), photo.get('originalformat'))

# map Flickr licenses to short names
def getLicense( num ):
  licenses = {}
  licenses['0'] = ''
  licenses['4'] = 'CC BY'
  licenses['5'] = 'CC BY-SA'
  licenses['6'] = 'CC BY-ND'
  licenses['2'] = 'CC BY-NC'
  licenses['1'] = 'CC BY-NC-SA'
  licenses['3'] = 'CC BY-NC-ND'

  if licenses[num] is None:
    return licenses[0]
  else:
    return licenses[num]


if __name__ == '__main__':
  import argparse

  parser = argparse.ArgumentParser(description='Backup your Flickr photos')
  parser.add_argument('--api-key', required=True, help='Flickr API key')
  parser.add_argument('--api-secret', required=True, help='Flickr API secret')

  config = parser.parse_args()

  # check if a fetched directory exist else create it
  createDirectorySafe('fetched')
  fetch(config.api_key, config.api_secret)