#!/usr/bin/python

#
# generate an album from a set of rules
#

import kimdaba_album
import os
import kid
kid.enable_import()
import one_image
import flat_image_list

class abstract_size:
    """Derive hard-coded sizes from this"""
    @classmethod
    def name(cls):
        return cls.__name__.replace("size","",1)
# or just construct these from real sizes?
# maybe scale_arg should be here too

class origsize(abstract_size):
    w,h = None, None
class thumbsize(abstract_size):
    w,h = 64,64

# image builder
class image_maker:
    def __init__(self, inbase, base, sizes, force=False):
        self.inbase = inbase
        self.base = base
        self.sizes = sizes
        self.force = force
    def sizetag(self, size):
        if hasattr(size, "name"):
            return size.name()
        else:
            return "%sx%s" % size
    def destname(self, img, size):
        name, ext = img.rsplit(".",1)
        extra = self.sizetag(size)
        return os.path.join(self.base, name + "_" + extra + "." + ext)

    def pathmap(self, source_image):
        imgname = os.path.basename(source_image)
        return dict([(size, self.destname(imgname, size)) for size in self.sizes])

    def scale_arg(self, size):
        if isinstance(size, tuple):
            w,h = size
        elif size.w and size.h:
            w,h = size.w, size.h
        else:
            return ""
        return "-scale %sx%s" % (w,h)

    def generate(self, img, prev=None, next=None):
        source_image = os.path.join(self.inbase, img.get("file"))
        imgname = os.path.basename(source_image)
        rotation = ""
        if img.get("angle") != "0":
            # be clever and use jpegtran if we can
            rotation = "-rotate %s" % img.get("angle")
            print "rotating", imgname, "by", rotation
        allsizes = [os.path.basename(self.destname(imgname, s) )
                    for s in self.sizes]
        for size in self.sizes + [thumbsize]:
            dst = self.destname(imgname, size)
            dst_prev = None
            if prev:
                dst_prev = os.path.basename(self.destname(prev.get("file"), size))
            dst_next = None
            if next:
                dst_next = os.path.basename(self.destname(next.get("file"), size))
            # convert the image (the way bins did it?)
            if self.force and os.path.exists(dst): 
                os.remove(dst)
            # still need rotate arg!
            if not os.path.exists(dst):
                st = os.system("set -x; convert %s %s %s %s" %
                               (rotation, self.scale_arg(size), source_image, dst))
                if st:
                    raise Exception("convert blew out")
            if size == thumbsize: 
                # give up after the image, for thumbs
                continue
            template = one_image.Template(img=img,
                                          imglink=os.path.basename(dst),
                                          prev=dst_prev, next=dst_next,
                                          allsizes=allsizes)
            outlink = dst + ".html"
            template.write(outlink)

    def make_flat_index(self, outpath, images, title):
        outindex = os.path.join(outpath, "index.html")
        allsizes = [(os.path.basename(img.get("file")),
                     os.path.basename(self.destname(img.get("file"), thumbsize)),
                     [(self.sizetag(s),
                       os.path.basename(self.destname(img.get("file"), s)))
                      for s in self.sizes])
                    for img in images]
        template = flat_image_list.Template(all=allsizes, title=title)
        template.write(outindex)


def prev_curr_next(i):
    i = iter(i)
    prev = None
    curr = i.next()
    for next in i:
        yield prev, curr, next
        prev = curr
        curr = next
    yield prev, curr, None

class album:
    def __init__(self):
        self.filename = kimdaba_album.kimdaba_default_album()
        self.elements = kimdaba_album.parse(self.filename)
        self.keys_in = set()
        self.keys_out = set()
        self._title = ""
        self._description = ""
        self._sizes = []
    def include_keywords(self, *kw):
        # check against keywords actually existing?
        self.keys_in.update(kw)
    def exclude_keywords(self, *kw):
        # check against keywords actually existing?
        self.keys_out.update(kw)
    def title(self, txt):
        self._title = txt
    def description(self, txt):
        self._description = txt
    def sizes(self, *sz):
        # check for validity?
        self._sizes.extend(sz)
    def generate(self, outpath, noisy=True):
        images = kimdaba_album.select_images(self.elements, self.keys_in, self.keys_out)
        inbase = self.elements.findall("config")[0].get("imageDirectory")
        maker = image_maker(inbase, outpath, self._sizes)
        # don't see an itertools way to do it...
        for img_p, img, img_n in prev_curr_next(images):
            if noisy: print "img", img.get("file")
            maker.generate(img, prev=img_p, next=img_n)
            # use maker.pathmap to get the things to href

        maker.make_flat_index(outpath, images, self._title)

        # for all images
        #    generate the sizes
        #    generate the single-image page for each size
        # -- later, don't regnerate what's already there
        # -- also, generate "up" links to the indices:
        # generate time-oriented index page
        # generate number-oriented index page

        # just to get started, one single flat image page...
        

# if __name__ == "__main__":