import sys
import Image
import array
import gameduino.compress as compress
import gameduino.prep as gdprep

hh = open("asteroidgraphics.h", "w")

class Indexer(object):

    def __init__(self):
        self.v = {}
        self.i = []

    def index(self, d):
        if not d in self.v:
            self.v[d] = len(self.v)
            self.i.append(d)
        return self.v[d]

    def __len__(self):
        return len(self.v)

    def __iter__(self):
        return self.i.__iter__()

title = Image.open("title.png").convert("L")
lines = Indexer()
indices = []
for x in range(512):
    strip = title.crop((x, 0, x + 1, 75))
    indices.append(lines.index(strip.tostring()))

def runs(binary):
    if True in binary:
        a = binary.index(True)
        if False in binary[a:]:
            b = a + binary[a:].index(False)
        else:
            b = len(binary)
        return [(a, b)] + [(b + c, b + d) for (c, d) in runs(binary[b:])]
    else:
        return []

def runlist(rlc):
    r = list(sum(rlc, ()))
    r[-1] |= 0x80
    return r

runtab = []
for i,d in enumerate(lines):
    binary = [ord(c) > 0 for c in d]
    runtab.append(runs(binary))

# Now find duplicate sequences in the runs, by adding runs (longest first)
# to a string (runstr) and detecting duplicate runs.
# The payoff is that the number of runs is reduced below 256, so the line offset
# can be a byte

runstr = ""
runtabL = sorted(runtab, lambda a,b: cmp(len(b),len(a)))
for rlc in runtabL:
    if rlc:
        s = "".join([chr(a) for a in runlist(rlc)])
        if s in runstr:
            pass
        else:
            runstr += s
        assert (runstr.index(s) & 1) == 0
gdprep.dump(hh, "title_runs", array.array('B', runstr))
print >>hh, "static PROGMEM prog_uchar title[] = {"
for i in indices:
    if runtab[i]:
        s = "".join([chr(a) for a in runlist(runtab[i])])
        v = runstr.index(s) / 2
    else:
        v = 0xff
    print >>hh, "%d," % v
print >>hh, "};"

ir = gdprep.ImageRAM(hh)

names = [ "explode32", "explode16" ]
(explode32,explode16) = gdprep.palettize([Image.open(nm + ".png") for nm in names], 16)
gdprep.dump(hh, "palette16a", gdprep.getpal(explode32))
ir.addsprites("explode32", (32,32), explode32, gdprep.PALETTE16A, center = (16,16))
ir.addsprites("explode16", (16,16), explode16, gdprep.PALETTE16A, center = (8,8))

names = [ "rock0r", "rock1r" ]
(rock0r,rock1r) = gdprep.palettize([Image.open(nm + ".png") for nm in names], 16)
gdprep.dump(hh, "palette16b", gdprep.getpal(rock0r))
ir.addsprites("rock0r", (16,16), rock0r, gdprep.PALETTE16B, center = (8,8))
ir.addsprites("rock1r", (32,32), rock1r, gdprep.PALETTE16B, center = (16,16))

sparkr = gdprep.palettize(Image.open("sparkr.png"), 4)
gdprep.dump(hh, "palette4a", gdprep.getpal(sparkr))
ir.addsprites("sparkr", (16,16), sparkr, gdprep.PALETTE4A, center = (8,8))

player = gdprep.palettize(Image.open("player.png"), 16)
gdprep.dump(hh, "palette256a", gdprep.getpal(player))
ir.addsprites("player", (32,32), player, gdprep.PALETTE256A + gdprep.PALETTE256B, center = (16,16))

cc = compress.Codec(b_off = 9, b_len = 3)
uncompressed = ir.used().tostring()
gdprep.dump(hh, "asteroid_images_compressed", cc.toarray(uncompressed))

fn = "bg"
(picdata, chrdata, paldata) = gdprep.encode(Image.open("bg.png"))
gdprep.dump(hh, "%s_pic" % fn, picdata)
gdprep.dump(hh, "%s_chr_compressed" % fn, cc.toarray(chrdata.tostring()))
gdprep.dump(hh, "%s_pal_compressed" % fn, cc.toarray(paldata.tostring()))

ramp = Image.open("title_ramp.png").convert("RGB")
li = array.array('B', ramp.tostring()).tolist()
rgbs = zip(li[0::3], li[1::3], li[2::3])
gdprep.dump(hh, "title_ramp", array.array('H', [gdprep.rgb555(*p) for p in rgbs]))
