#!/usr/bin/env python
import os
import os.path
import sys
#sys.path.pop(0)
import urllib2
import time


first_uri = 'http://b.andy.sandbox.cloudmade.com/tiles/cycle/%d/%d/%d.png'
#path = 'http://127.0.0.1:7777/tiles/cycle/%d/%d/%d.png'
fallback_uri = 'http://c.tile.openstreetmap.org/%d/%d/%d.png'
fallback_uri = 'http://c.tah.openstreetmap.org/Tiles/tile/%d/%d/%d.png'
age_threshold = 60 * 60 * 24
delete_threshold = 60 * 60 * 24 * 30


lowzoom = [first_uri, fallback_uri]
highzoom = [fallback_uri, fallback_uri]


summary = {'deleted': 0,
	'downloaded': 0,
	'skipped': 0,
	'errors': 0,
	'up to date': 0,
	'failures': 0,
	'checked': 0,
	'ignored': 0,
	'updated': 0}


class DownloadError(Exception):
    pass


def get_file(full_path, url, force=False):
    if force:
        hdrs = {}
    else:
        hdrs = {'If-Modified-Since': time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime(os.stat(full_path)[-2]))}
    request = urllib2.Request(url, headers=hdrs)
    o = urllib2.urlopen(request)

    a = o.read()
    if len(a) == 0:
        raise Exception('Downloaded empty file.')
    outp = open(full_path, 'w')
    outp.write(a)
    outp.close()    


def download(file_path, uri_list, params, force=False):
    """Returns True if file was downloaded, False if it's up to date"""
    # TODO: exception if failed
    a, b, c = params
    stats = os.stat(file_path)
    
    for uri in uri_list:
        try:
            get_file(file_path, uri % (a, b, c), force)
            os.utime(file_path, (stats.st_atime, time.time())) # is this needed?
            return True
        except urllib2.HTTPError, e:
            if e.code == 304:
                os.utime(file_path, (stats.st_atime, time.time()))
                print 'Up to date'
                return False
            print e, 'falling back'
        except Exception, e:
            print e, 'falling back'
        summary['errors'] += 1
    raise DownloadError('Every mirror failed: ' + file_path)


if __name__ == '__main__':
    usage = """Usage: fill_gaps.py [options] [host1] [host2] ...
    Options:
    -r time	Remove tiles accessed at least time seconds ago. 0 means this feature is disabled
    -s time	Skip updating tiles checked at most time seconds ago (empty files will be checked regardless)
    -c	Compact output: don't display summary
    -m	Display file modification age if updating
    -a	Display file access age if updating
"""
    import sys
    print_summary = True
    show_mage = False
    show_aage = False
    i = 1
    while i < len(sys.argv):
        a = sys.argv[i]
        if a == '-r':
            i = i + 1
            delete_threshold = int(sys.argv[i])
            if delete_threshold == 0:
                delete_threshold = ()
        elif a == '-s':
            i = i + 1
            age_threshold = int(sys.argv[i])
        elif a == '-c':
            print_summary = False
        elif a == '-m':
            show_mage = True
        elif a == '-a':
            show_aage = True
        else:
            raise Exception('Unknowparametern')
        i = i + 1
    try:
        for dir_, subdirs, files in os.walk('.'):
            for file_ in files:
                file_path = os.path.join(dir_, file_)
                try:
                    root, a, b, c = file_path[:-4].split('/') #TOSO: change to sys.path
                    a, b, c = int(a), int(b), int(c)
                except:
                    summary['ignored'] += 1
                    print file_path, 'ignored'
                    continue

                summary['checked'] += 1
                if a > 14 or a == 12:
                    uris = highzoom
                else:
                    uris = lowzoom

                stats = os.stat(file_path)
#                print stats
 #               raw_input()
                if time.time() - stats.st_atime > delete_threshold:
                    print 'DELETE', file_path, (time.time() - stats.st_atime) / (24*3600)
                    os.unlink(file_path)
                    summary['deleted'] += 1
                elif stats.st_size == 0:
                    print 'NULL', file_path
                    try:
                        if download(file_path, uris, (a, b, c), True):
                            summary['downloaded'] += 1
                        else:
                            raise ImpossibleError
                
                    except DownloadError, e:
                        summary['failures'] += 1
 
                elif time.time() - stats.st_mtime > age_threshold:
                    ending = ''
                    if show_mage:
                        td = time.time() - stats.st_mtime
                        hours = td / 3600
                        days, hours = hours / 24, hours % 24
                        ending = ending + 'mod. %3dd %02dh ' % (days, hours)
                    if show_aage: 
                        td = time.time() - stats.st_atime
                        hours = td / 3600                  
                        days, hours = hours / 24, hours % 24
                        ending = ending + 'acc. %3dd %02dh' % (days, hours)
       
                    print 'FULL', file_path, ending
                    try:
                        if download(file_path, uris, (a, b, c), False):
                            summary['updated'] += 1
                        else:
                            summary['up to date'] += 1
                    except DownloadError, e:  
                        summary['failures'] += 1

                else:
                    summary['skipped'] += 1
    except KeyboardInterrupt:
        pass
    if print_summary:
        for item in summary.items():
            print '%s:\t%d' % item
