#!/usr/bin/python
import os
import sys
try:
    import cElementTree as etree
except ImportError:
    import elementtree.ElementTree as etree

# tool for manually extracting albums from kimdaba.

# For example,
# Src: ~/PIX/SL300RT/downcase/index.xml
# Dest: ~/metacarta/static/metacarta/
# Sizes: Full, 800x600
# Title: MetaCarta Pictures
# Desc: random pictures I've taken around the office
# Search: "work" in keywords
## consider a subalbum:
## "work" in keywords and "whiteboard" in keywords
## later, disambiguate "work"

# picture for keywords:
# /KimDaBa/config has interesting stuff, but isn't a picture
# /KimDaBa/options/option/value@value is interesting too
# /KimDaBa/member-groups/member@group-name, @category, @member
#   is how we pre-cook groups, because otherwise we don't record them
# /KimDaBa/images/image@file
# /KimDaBa/images/image where 
# /KimDaBa/images/image/options/option[@name="Keywords]/value[@value="work"]


# domgrep '/KimDaBa/images/image/options/option[@name="Keywords"]/value/@value' ~/PIX/SL300RT/downcase/index.xml
#   seems to at least dump all keywords; @name="Persons" does likewise...
# domgrep '/KimDaBa/images/image/options/option[@name="Keywords"]/value[@value="pouncing"]/@value' ~/PIX/SL300RT/downcase/index.xml
#   is kind of silly, in that it prints "pouncing" 40 times...
# domgrep '/KimDaBa/images/image/@file' ~/PIX/SL300RT/downcase/index.xml
#   prints all the filenames, but doesn't filter...
# domgrep '/KimDaBa/images/image[options/option[@name="Keywords"]/value[@value="pouncing"]]/@file' ~/PIX/SL300RT/downcase/index.xml
#   appears to filter filenames on pouncing, at least...
#
# in practice maybe we just pick up /KimDaBa/images/image/@md5sum, then
# key individual itmes with [md5sum=...]

# so:
##   <image width="2048" monthFrom="10" dayFrom="25" hourFrom="20" height="1536" yearTo="0" monthTo="0" md5sum="a2753c7c48e7b13a8b1a4b26a2be2e6d" minuteFrom="2" file="100cxbox/kicx6354.jpg" label="kicx6354" angle="0" dayTo="0" secondFrom="28" yearFrom="2005" description="" >
##    <options>
##     <option name="Keywords" >
##      <value value="whiteboard" />
##      <value value="work" />
##     </option>
##     <option name="Locations" >
##      <value value="MetaCarta" />
##     </option>
##    </options>
##   </image>
#
# we want to pull out the keywords for a text label (dt)
# we want all the image attrs:
# width="2048"
# height="1536" 

# yearFrom="2005" 
# monthFrom="10"
# dayFrom="25" 
# hourFrom="20" 
# minuteFrom="2" 
# secondFrom="28" 

# yearTo="0" 
# monthTo="0" 
# dayTo="0" 

# md5sum="a2753c7c48e7b13a8b1a4b26a2be2e6d" 
# file="100cxbox/kicx6354.jpg" 
# label="kicx6354" 

# angle="0"   # or 90
# description=""

# note that
# domgrep '/KimDaBa/images/image[options/option[@name="Keywords"]/value[@value="construction"]]/@*' ~/PIX/SL300RT/downcase/index.xml
# actually gets each attribute, but probably in file-order

# ee = elementtree.ElementTree.ElementTree(file=os.path.expanduser("~/PIX/SL300RT/downcase/index.xml"))
# img = ee.findall('images/image')[0]
# (ee.getiterator?)
# >>> img.keys()
# ['dayTo', 'secondFrom', 'yearFrom', 'angle', 'file', 'monthFrom', 'md5sum', 'yearTo', 'height', 'width', 'minuteFrom', 'hourFrom', 'monthTo', 'label', 'dayFrom', 'description']
# >>> img.find("options")
# <Element options at -482cceb4>
# img.find("options").find("option").keys()
# ['name']
# img.find("options").find("option").get("name")
# 'Keywords'
# >>> img.get("file")
# '100cxbox/kicx6300.jpg'
# >>> img.find("options").find("option/value").get("value")
# 'adventure'
# [f.get("value") for f in img.find("options").findall("option/value")]
# ['adventure', 'pouncing']
# [f.get("value") for f in img.findall("options/option/value")]
# ['adventure', 'pouncing']

def kimdaba_default_album():
    """Find the path to the default album kimdaba will start with"""
    # could support cheap comments with an early .split("#",1)[0]
    # but the kde files don't use them
    args = dict(line.rstrip("\n").split("=",1) 
                for line in file(os.path.expanduser("~/.kde/share/config/kimdaba")))
    return args["configfile"]

def parse(path):
    return etree.ElementTree(file=path)

def select_images(kimdabaroot, wantedkeys, unwantedkeys):
    results = []
    for img in kimdabaroot.findall("images/image"):
        thesekeys = wantedkeys.copy()
        imgkeys = set([f.get("value") for f in img.findall("options/option/value")])
        # remove the keys for this img; if anything is left,
        # they weren't all satisfied
        if not wantedkeys - imgkeys and not unwantedkeys & imgkeys:
            print img.get("file"), imgkeys
            results.append(img)
            # add image to album
    return results


# timg = [img for img in kimdabaroot.findall("images/image") if img.get("md5sum") == "26306475ed4af77aaab7a7102dff76b3"][0]
# print elementtree.ElementTree.tostring(timg.findall("options/option")[0])
# kws = timg.findall("options/option")[0]
# ES=elementtree.ElementTree.tostring
# print ES(kws.makeelement("value", dict(value="flickd")))
# kws.append(kws.makeelement("value", dict(value="flickd")))
# print ES(kws)
# kimdabaroot.write("/tmp/zot.xml", encoding="UTF-8")
def safe_replace(xpath, etree):
    """Safely replace a kimdaba index.xml file with a modified one"""
    # write temporary
    etree.write(xpath + "~")
    # move original out of the way, for recovery
    os.rename(xpath, xpath + ".bak")
    # move temporary in to place
    os.rename(xpath + "~", xpath)

def add_keyword(md5sum, value):
    """Add a keyword to an image for which we know the md5sum"""
    kimdabaxml = kimdaba_default_album()
    kimdabaroot = parse(kimdabaxml)
    for img in kimdabaroot.findall("images/image"):
        if img.get("md5sum") != md5sum: continue
        print "found", img.get("file")
        for optionset in img.findall("options/option"):
            if optionset.get("name") == "Keywords":
                optionset.append(optionset.makeelement("value",
                                                       dict(value=value)))
                safe_replace(kimdabaxml, kimdabaroot)
                return
    raise Exception("didn't match anything, add_keyword failed!")
                
def add_property(md5sum, propname, propvalue):
    """Add/Change a property to an image for which we know the md5sum"""
    kimdabaxml = kimdaba_default_album()
    kimdabaroot = parse(kimdabaxml)
    for img in kimdabaroot.findall("images/image"):
        if img.get("md5sum") != md5sum: continue
        print "found", img.get("file")
        if img.get(propname) != propvalue:
            img.set(propname, propvalue)
            safe_replace(kimdabaxml, kimdabaroot)
            return
    raise Exception("didn't find matching image, add_property failed!")

def add_description(pathpart, desc):
    """Add/Change description for an image, by partial name; return md5sum"""
    kimdabaxml = kimdaba_default_album()
    kimdabaroot = parse(kimdabaxml)
    for img in kimdabaroot.findall("images/image"):
        # file="100cxbox/kicx6848.jpg", or now year/...
        if img.get("file") == pathpart:
            img.set("description", desc)
            safe_replace(kimdabaxml, kimdabaroot)
            return img.get("md5sum")
    raise Exception("no images had path part %s, add_description failed" % pathpart)

def expand_keyword_groups(kimdabaroot, keywords):
    """Expand keywords that are group members"""

    expansions = set()
    for member in kimdabaroot.findall("member-groups/member"):
        # '<member category="Keywords" group-name="Robot" member="Scooba" />\n  '
        # later, limit to member.get("category")
        if member.get("member") in keywords:
            expansions.add(member.get("group-name"))
    return expansions

if __name__ == "__main__":
    prog = sys.argv.pop(0)
    # use optparse to do real processing here:
    # --output=directory (to build album in)
    # --size*=[full|NxM] (size of images to make, first=default)
    # then the keys as already handled
    wantedkeys = set()
    unwantedkeys = set()
    # unwanted start with a "-"
    # consider maybe adding K: L: P: for categories, optionally...
    for key in sys.argv:
        if key.startswith("-"):
            unwantedkeys.add(key[1:])
        else:
            wantedkeys.add(key)

    kimdabaxml = kimdaba_default_album()
    kimdabaroot = parse(kimdabaxml)
    images = select_images(kimdabaroot, wantedkeys, unwantedkeys)
    print len(images)