#!/usr/bin/python
# from ~/Desktop/downloads/PythonWeb.org/web/image/graph.py:
#         self.image=PIL.Image.new("RGB", size, bgColor)
#         self.draw=PIL.ImageDraw.Draw(self.image)
#         self.font = PIL.ImageFont.truetype(font,12) 
# look at ~/Desktop/downloads/schoolbell-m7.1/src/schooltool/rest/infofacets.py
#   just to see why it is called that, even though it only mucks with images

# what does sysinfo.displaypixels() return?

# portrun python
import sys
sys.path.append("/opt/local/lib/python2.4/site-packages/")

import PIL
import PIL.Image
import PIL.ImageDraw

import os

imgbase = os.path.expanduser("~/symbian/BACKUP/current/Images/")

# lifted from bcpathtrace.py:
def old_to_new(val):
    if str(val)[-1] not in "NSEW":
        return float(val)
    newval = float(val[:-1])/100.0
    if val[-1] in "SW":
        newval = -newval
    return newval

def scan_where():
    fields = {}
    for f in os.listdir(imgbase):
        if not f.endswith(".where"): continue
        imgpath = os.path.join(imgbase, f)
        if os.path.exists(imgpath.replace(".where",".bad")): continue
        bits = open(imgpath,"r").read()
        if bits.startswith("("): words=eval(bits)
        else: words=bits.split(" ")
        lat, lon = map(old_to_new,words[:2])
        when, discard = os.path.splitext(f)
        fields[when] = (lat, lon)
    return fields

class scaler:
    def __init__(self, insamp):
        self.inmin = insamp
        self.inmax = insamp
        self.outmin = None
        self.outmax = None
    def addval(self, v):
        self.inmin = min(self.inmin, v)
        self.inmax = max(self.inmax, v)
    def scale(self, v):
        inrange = self.inmax - self.inmin
        outrange = self.outmax - self.outmin
        return self.outmin + outrange *(v - self.inmin)/inrange
    def center(self):
        inrange = self.inmax - self.inmin
        return self.inmin + inrange/2

# modified from original to take the PIL.Image
def make_scalers(points, c):
    order = points.keys()
    order.sort()
    samplat, samplon = points[order[0]]
    latscale = scaler(samplat)
    lonscale = scaler(samplon)

    for lat, lon in points.values():
        latscale.addval(lat)
        lonscale.addval(lon)

    max_x,max_y = c.size

    latscale.outmin = 0
    latscale.outmax = max_y
    lonscale.outmin = 0
    lonscale.outmax = max_x

    return latscale, lonscale, order

# unified aspect-preserving scalers are harder, because we *don't*
# just want 1:1, we need full generality:
# >>> math.cos(math.radians(57.417))
# 0.539 for Gothenburg,
# 0.740 for Boston (42.3)
# 0.511 for Stockholm (59.243)

def find_days(points):
    days = {}
    for k in points.keys():
        d,t = k.split("t")
        days[d] = days.get(d,0) + 1
    daylist = days.keys()
    daylist.sort()
    # require 2 points for a day to count
    return [day for day in daylist if days[day] > 2]

def points_of_day(points, day):
    subpoints = {}
    for k,v in points.items():
        d,t = k.split("t")
        if d == day:                    # or say d.startswith(day) to handle prefix hours?
            subpoints[k] = v
    return subpoints

def bothscale(point, latscale, lonscale):
    lat, lon = point
    return (latscale.scale(lat), lonscale.scale(lon))

def latlon_to_xy(point, latscale, lonscale):
    neglat, lon = bothscale(point, latscale, lonscale)
    return lon, latscale.outmax - neglat

blue = (0,0,255)
green = (0,255,0)
red = (255,0,0)
yellow = (255,255,0)

if __name__ == "__main__":
    allpoints = scan_where()
    days = find_days(allpoints)

    # enumerate isn't in 2.2, but the mac side starts with 2.3...
    for dayno, thisday in enumerate(days):
        target_size = (192,204) # copy value from sysinfo.displaypixels()
        image = PIL.Image.new("RGB", target_size, 0)
        draw = PIL.ImageDraw.Draw(image)
        # what follows is lifted from bcpathtrace.render()
        max_x,max_y = target_size # or image.size...
        points = points_of_day(allpoints, thisday)
        latscale, lonscale, order = make_scalers(points, image)
        label = u"Day %s/%s: c %.4s,%.4s" % (dayno+1, len(days), 
                                             latscale.center(),lonscale.center())
        # ds.text( (0,max_y), label, yellow)
        draw.setink(yellow)
        textwidth, textheight = draw.textsize(label)
        draw.text( (0,max_y - textheight), label )

        lastpoint = points[order.pop(0)]
        draw.setink(blue)
        draw.point(latlon_to_xy(lastpoint, latscale, lonscale) ) # width=4)
        # turns out that there's no equivalent to point(width) other than manually drawing a chord...
        # and PIL includes no docs on the args to chord, though guesses work ok...

        # lastd, lastt = order[0].split("t")
        for k in order:
            # sleep makes the rendering order visible, but we don't need that with a cursor
            # e32.ao_sleep(0.1)
            thispoint = points[k]
            # plot from lastpoint to thispoint, scaled by size
            draw.setink(green)
            draw.line( (latlon_to_xy(lastpoint, latscale, lonscale), latlon_to_xy(thispoint, latscale, lonscale)) )
            lastpoint = thispoint

        image.save(open("/tmp/uda%s.jpg" % thisday, "w"), format="JPEG")