#!/usr/bin/env python
from __future__ import print_function
from PIL import Image
import re, sys, json, os

try:
    from urllib import quote as urlquote # Python 2.X
except ImportError:
    from urllib.parse import quote as urlquote # Python 3+


def fitbox (boxw, boxh, w, h):
    rw = boxw
    rh = int(rw * (float(h) / w))
    if (rh >= boxh):
        rh = boxh
        rw = int(rh * (float(w) / h))
    return rw, rh

def tile_image (im, maxz=0, tilew=256, tileh=256, base=".", template="z{0[z]}y{0[y]}x{0[x]}.jpg", bgcolor=(0,0,0), margin_right=0, margin_bottom=0):
    z = 0
    boxw, boxh = tilew, tileh

    alpha = bgcolor != None # not template.endswith("jpg")

    while True:
        rw, rh = fitbox(boxw, boxh, im.size[0], im.size[1])
        rim = im.resize((rw-margin_right, rh-margin_bottom), Image.ANTIALIAS)
        if bgcolor:
            tim = Image.new("RGB", (boxw, boxh), bgcolor)
            tim.paste(rim, (0, 0))
        else:
            tim = Image.new("RGBA", (boxw, boxh))
            tim.paste(rim, (0, 0))

        rows, cols = 2**z, 2**z
        for r in range(rows):
            for c in range(cols):
                ix = c*tilew
                iy = r*tileh
                cim = tim.crop((ix, iy, ix+tilew, iy+tileh))
                op = base + template.format({'z':z, 'x':c, 'y':r})
                # if not alpha:
                #     cim = cim.convert("RGB")
                cim.save(op)

        z += 1
        if z>maxz:
            break
        boxw *= 2
        boxh *= 2

def expand_template (x):
    return re.sub(r"{(\w+?)}", "{0[\\1]}", x)

if __name__ == "__main__":
    from argparse import ArgumentParser

    ap = ArgumentParser("Generate image tiles and output JSON for a collection of images")
    ap.add_argument("input", nargs="+")

    ap.add_argument("--basepath", default=".")
    ap.add_argument("--baseuri", default="")

    ap.add_argument("--tilespath", default="tiles", help="name of path to create in the same folder as the original")
    ap.add_argument("--tilewidth", type=int, default=256)
    ap.add_argument("--tileheight", type=int, default=256)
    ap.add_argument("--zoom", type=int, default=3)
    ap.add_argument("--tilename", default="z{z}y{y}x{x}.png")
    ap.add_argument("--force", default=False, action="store_true")

    args = ap.parse_args()

    """
    leafygal format: {id: original, tiles: "template", name: filename}
    """

    tilenamex = expand_template(args.tilename)
    #bgcolor = (0, 0, 0)
    bgcolor = None
    items = []

    for imgpath in args.input:
        parent = os.path.split(imgpath)[0]
        basename = os.path.basename(imgpath)
        path = os.path.join(parent, args.tilespath, basename)
        item = {
            'id': urlquote(imgpath),
            'name': basename,
            'tiles': os.path.join(path, args.tilename)
        }
        tile0 = os.path.join(path, tilenamex.format({'x': 0, 'y': 0, 'z': 0}))
        items.append(item)
        if not os.path.exists(tile0) or args.force:
            print ("Tiling {0}".format(imgpath), file=sys.stderr)
            try:
                im = Image.open(imgpath)
                try:
                    os.makedirs(path)
                except OSError:
                    pass
                tile_image(im, args.zoom, args.tilewidth, args.tileheight, path+"/", tilenamex, bgcolor)
                # tiles.append(t)

            except IOError as e:
                print ("Missing {0}, skipping".format(n), file=sys.stderr)
                items = items[:-1]

    data = {
        '@context': {
            'id': '@id',
            'aa': 'http://activearchives.org/terms',
            'name': 'aa:filename',
            'tiles': 'aa:tiles'
        },
        '@graph': items
    }
    print (json.dumps(data, indent=2))
