#!/usr/bin/python

from struct import unpack
import binascii

def read_curve(acv_file):
    curve = []
    nr_points, = unpack("!h", acv_file.read(2))
    for j in range(nr_points):
        y, x = unpack("!hh", acv_file.read(4))
        curve.append((x, y))
    return curve

def acv_collect_curves(acv_file):
    _, nr_curves = unpack("!hh", acv_file.read(4))

    curves = []
    for i in range(nr_curves):
        curves.append(read_curve(acv_file)) 
    return curves

def to_short(x):
    return int((x / 255.0) * 65535.0)

def to_bibble_curves(curves):
    b_curves = []

    for curve in curves:
        b_curve = []
        for x, y in curve:
            b_curve.append((to_short(x), to_short(y)))
        b_curves.append(b_curve)
    return b_curves

def right_pad_curve(curve, nr_points=9):
    for i in range(nr_points - len(curve)):
        curve.append((0,0)) 
    return curve

def xes(curve):
    l = []
    for x, _ in curve:
        l.append(x)
    return l

def ys(curve):
    l = []
    for _, y in curve:
        l.append(y)
    return l

def flatten(x):
    result = []
    for el in x:
        if hasattr(el, "__iter__"):
            result.extend(flatten(el))
        else:
            result.append(el)
    return result

def generate_bch(curves, outf):
    curves = to_bibble_curves(curves)

    rgb = r = g = b = [(0, 0), (65535, 65535)] 

    for i, curve in enumerate(curves):
        if i == 0:
            rgb = curve
        elif i == 1:
            r = curve
        elif i == 2:
            g = curve
        elif i == 3:
            b = curve

    print >> outf, "[curves]"
    print >> outf, "curves_m_cn=4,%d,%d,%d,%d" % (len(rgb), len(r),
                                                  len(g), len(b))

    # Now we need to pad the curves here and there
    # Bibble puts the curve in one array.
    pad_to = max(len(rgb), len(r), len(g), len(b), 16)

    prgb = right_pad_curve(rgb, pad_to)
    pr = right_pad_curve(r, pad_to)
    pg = right_pad_curve(g, pad_to)
    pb = right_pad_curve(b, pad_to)

    # I'm not sure what the zero's are doing in front of the
    # array with points.
    print >> outf, "curves_m_cx=4,%d,0,0,0,0," % (len(prgb) + 1),
    print >> outf, ",".join(map(str, flatten(map(xes, zip(prgb, pr, pg, pb)))))
    print >> outf, "curves_m_cy=4,%d,0,0,0,0," % (len(prgb) + 1),
    print >> outf, ",".join(map(str, flatten(map(ys, zip(prgb, pr, pg, pb)))))

    # We don't touch these values...
    print >> outf, """curves_m_ihi=4,65535,65535,65535,65535
curves_m_ilo=4,0,0,0,0
curves_m_imid=4,1.000000,1.000000,1.000000,1.000000
curves_m_ohi=4,65535,65535,65535,65535
curves_m_olo=4,0,0,0,0
curves_m_ver=0
curveschanged=255
curvesmode=0
curveson=true

[nogroup]
version=8.2
"""

# acv to bch conversion
if __name__ == '__main__':
    import sys

    if len(sys.argv) < 2:
        print "Usage: acv2bch.py curve(s)"

    for fn in sys.argv[1:]:
        outfn = fn.replace('.acv', '.bch')
        print "Converting:", fn, "to Bibble curve:", outfn
        outf = open(outfn, 'w')
        try:
            generate_bch(acv_collect_curves(open(fn, 'rb')), outf)
        finally:
            outf.close()
        

