#!/usr/bin/python

import os, sys, time

# options that can be modified here
subfolder_name = "album"
indexpage_name = "index.html"
thumbspage_name = subfolder_name + "/thumbs.html"
thumb_suffix = "_thumb"
medium_suffix = "_medium"
thumbsize = "90x90"
mediumsize = "600x500"
zipfile = "photos.zip"
backpage = "../index.html"         # Link to "Back to main page"
version = "1.00"

# options that can be modified by the commandline
class options:
    do_printinfo = False
    do_printusage = False
    do_forcedelete = False
    do_zip = False
    do_showfilename = False

def print_info():
    print
    print "makealbum.py version %s. (C) Axel Brink 2007." % version
    print "Execute in a directory with images. Creates a file '" + indexpage_name + "'"
    print "and a subdirectory '" + subfolder_name + "' containing thumbnails and medium-sized"
    print "images to form a simple web-album."
    print

def print_usage():
    print "Usage:"
    print os.path.basename(sys.argv[0]) + " [options] files"
    print "Options:"
    print "  -h, --help: print this help message"
    print "  -f:         force removal of old " + indexpage_name + " and " + subfolder_name + "/ before starting"
    print "  -n:         display the file name below every thumbnail"
    print "  -z:         create a zip file (takes time to create and space to store)"
    print "Example:"
    print "  " + os.path.basename(sys.argv[0]) + " -f -z *"
    print

def HTMLheader(title):
    """ Return a string with a HTML header including title"""
    return "<HTML>\n<HEAD>\n  <TITLE>" + title + "</TITLE>\n</HEAD>\n"

def HTMLfooter():
    """ Return a string with a HTML footer"""
    return "</HTML>\n"

def fix_filename(filename):
    """ Adds backslashes before unsafe characters (currently only spaces and semicolons) """
    fixed = filename.replace(' ', '\ ')
    fixed = fixed.replace(';', '\;')
    fixed = fixed.replace('(', '\(')
    fixed = fixed.replace(')', '\)')
    return fixed

def fix_filename_HTML(filename):
    """ Changes spaces into %20's """
    fixed = filename.replace(' ', '%20')
    fixed = filename.replace(';', '%3B')
    return fixed

def make_indexpage(leftpage, rightpage):
    """ Make index page file which displays leftpage and rightpage """
    indexfile = open(indexpage_name, 'w')
    indexfile.write(HTMLheader("Photo album"))
    indexfile.write('<FRAMESET COLS="150, *">\n')
    indexfile.write('  <FRAME src="' + leftpage + '" name="thumbsframe">\n')
    if rightpage == None:
        indexfile.write('  <FRAME name="photoframe">\n')
    else:
        indexfile.write('  <FRAME src="' + rightpage + '" name="photoframe">\n')
    indexfile.write('</FRAMESET>\n')
    indexfile.write(HTMLfooter())
    indexfile.close()

def link_to(address, name, target=None):
    """ Return a HTML link as a string """

    linktext = '<A href="' + address + '"'
    if target != None:
        linktext += ' target="' + target + '"'
    linktext += ">" + name + "</A>"
    return linktext

def generate(inputfilenames):
    """ Create index page, subfolder and sized photos """
    global options
    zipfilepath = os.path.join(subfolder_name, zipfile)

    # make thumbnail page
    os.mkdir(subfolder_name)
    thumbsfile = open(thumbspage_name, 'w')
    thumbsfile.write(HTMLheader("Thumbnails"))
    thumbsfile.write('<BODY>\n')
    thumbsfile.write(link_to(backpage, "<< back to main page", "_top"))
    thumbsfile.write('<P>\n')
    firstfile = True

    for inputfilename in inputfilenames:
        if not os.path.isfile(inputfilename):
            print "Skipping " + inputfilename
            continue

        print "Processing " + inputfilename

        # make thumbnail
        filedir, filetitle = os.path.split(inputfilename)
        filebase, fileext = os.path.splitext(filetitle)
        
        if fileext in ['.jpg', '.jpeg', '.JPG', '.JPEG', '.gif', '.GIF', '.png', '.PNG', '.pgm', '.PGM', '.tif', '.tiff', '.TIF', '.TIFF']:
            # this is an image
            thumb_filetitle = filebase + thumb_suffix + ".jpg"
            thumb_filename = os.path.join(subfolder_name, thumb_filetitle)
            
            command = "convert -quality 70 -resize " + thumbsize + " " +                fix_filename(inputfilename) + " " + fix_filename(thumb_filename)
            os.system(command)
            
            # make medium-sized image
            medium_filetitle = filebase + medium_suffix + ".jpg"
            medium_filename = os.path.join(subfolder_name, medium_filetitle)
            command = "convert -quality 75 -resize " + mediumsize + " " + fix_filename(inputfilename) + " " + fix_filename(medium_filename)
            os.system(command)
            
            # make link on thumbnail page
            if options.do_showfilename:
                link_name = '<IMG SRC="%s"> %s' % (fix_filename_HTML(thumb_filetitle), filetitle)
            else:
                link_name = '<IMG SRC="%s">' % fix_filename_HTML(thumb_filetitle)
            thumbsfile.write(link_to(address=fix_filename_HTML(medium_filetitle),
                                     name=link_name, target="photoframe"))
                                     
            thumbsfile.write('<BR>\n<FONT size=-1>(')
            sizetext = "%.1f MB" % (float(os.path.getsize(inputfilename)) / float(1024*1024))
            thumbsfile.write(link_to(address='../' + fix_filename_HTML(inputfilename),
                                     name="full size",
                                     target="photoframe"))
            thumbsfile.write(': ' + sizetext + ')</FONT><P>\n')
            thumbsfile.flush()

            # zip high-quality file
            if options.do_zip:
                command = "zip " + zipfilepath + " " + fix_filename(inputfilename) + " > /dev/null"
                os.system(command)
            
            # if this is the first image, show it initially
            if firstfile:
                firstfile = False
                make_indexpage(thumbspage_name, fix_filename_HTML(medium_filename))
        elif filetitle == indexpage_name:
            # skip the index.html
            pass
        else:
            # this is not an image; create a boring simple link
            # make link on thumbnail page
            thumbsfile.write('[<A href="../' + fix_filename_HTML(filetitle) + '" target="photoframe">')
            thumbsfile.write(filetitle + '</A>]<P>\n')
            thumbsfile.flush()
            if firstfile:
                firstfile = False
                make_indexpage(thumbspage_name, None)

            # zip file
            if options.do_zip:
                command = "zip " + zipfilepath + " " + fix_filename(inputfilename) + " > /dev/null"
                os.system(command)

    if options.do_zip:
        thumbsfile.write('<A href="' + zipfile + '">Download everything</A> (as a zipfile)<BR><P>\n')
    thumbsfile.write(link_to(backpage, "<< back to main page", "_top"))
    thumbsfile.write('<P>\n')
    thumbsfile.write('<FONT size="-2">Generated: ' + time.strftime("%c") + '</FONT>\n')
    thumbsfile.write('</BODY>\n')
    thumbsfile.write(HTMLfooter())
    thumbsfile.close()

    print "Created " + indexpage_name + " and " + subfolder_name + "."

def parse_options(args):
    """ Read commandline arguments and process options; return remaining arguments """
    global options

    if len(args) == 0:
        options.do_printinfo = True

    while len(args) > 0:
        if args[0][0] == '-':
            keyword = args[0]
            args = args[1:]
            if keyword == '-f':
                options.do_forcedelete = True
            elif keyword == '-z':
                options.do_zip = True
            elif keyword == '-n':
                options.do_showfilename = True
            elif keyword in ['-h', '--help']:
                options.do_printinfo = True
                options.do_printusage = True
            else:
                print "Unknown option: " + keyword
                options.do_printusage = True
                break
        else:
            break

    if len(args) == 0:
        # no files specified after the options
        print "No files specified."
        options.do_printusage = True
    return args

if __name__ == "__main__":
    remaining_args = parse_options(sys.argv[1:])

    if options.do_printinfo:
        print_info()

    if options.do_printusage:
        print_usage()
        sys.exit(0)

    if options.do_forcedelete:
        # forced removal of index.html and album/
        os.system("rm -rf index.html album/")

    if os.path.exists(indexpage_name):
        print "Error: file '" + indexpage_name + "' already exists. Before recreating, type 'rm -r album/ index.html' or use the -f option."
        sys.exit(1)

    if os.path.exists(subfolder_name):
        print "Error: folder '" + subfolder_name + "' already exists. Before recreating, type 'rm -r album/ index.html' or use the -f option."
        sys.exit(1)

    generate(remaining_args)
