#!/usr/bin/env python
from __future__ import print_function

import gameduino2.registers as gd2
import gameduino2.prep

import os
import array

from PIL import Image
import wave
import audioop

formats = ('L1', 'L2', 'L4', 'L8', 'RGB332', 'ARGB2', 'ARGB4', 'RGB565', 'ARGB1555')

def cname(s):
    """ make name s C-friendly """
    for c in "-+.":
        s = s.replace(c, "_")
    return s.upper()

class GD2Assets(gameduino2.prep.AssetBin):

    def __init__(self, cmdline, opts, args):
        self.opts = opts
        self.args = args
        gameduino2.prep.AssetBin.__init__(self)
        self.header = opts.get('-o', 'default_assets.h')
        self.header_intro = "// This file was generated with the command-line:\n//    " + cmdline + "\n\n"

        if '-f' in opts:
            self.asset_file = opts['-f']
        if '-3' in opts:
            self.target_810()

        self.handlers = {
            'png' : (self.image, "PNG image file (options: format)"),
            'jpg' : (self.image, "JPEG image file (options: format)"),
            'bmp' : (self.image, "BMP image file (options: format)"),
            'gif' : (self.image, "GIF image file (options: format)"),
            'ttf' : (self.ttf, "TrueType font file (options: format, size, firstchar, charset, topchar)"),
            'otf' : (self.ttf, "OpenType font file (options: format, size, firstchar, charset, topchar)"),
            'wav' : (self.sample, "Audio sample, mono 16-bit (no options)"),
        }

    def parse_format(self, format):
        if format not in formats:
            print('ERROR: unknown format "%s"' % format)
            print()
            print('Formats are: %s' % " ".join(formats))
            sys.exit(1)
        return eval("gd2." + format)

    def image(self, suffix, ff, format = 'ARGB4'):
        name = cname(os.path.basename(ff[0])[:-1 - len(suffix)])
        self.load_handle(name,
                         [Image.open(f) for f in ff],
                         self.parse_format(format),
                         dither = '-d' in self.opts)

    def ttf(self, suffix, f, size = '12', format = 'L4', firstchar = '32', topchar = '127', charset = None):
        name = cname(os.path.basename(f[0])[:-1 - len(suffix)])
        self.load_ttf(name, f[0], int(size), self.parse_format(format),
                      firstchar = int(firstchar, 0),
                      topchar = int(topchar, 0),
                      charset = charset)

    def sample(self, suffix, f):
        name = os.path.basename(f[0])[:-1 - len(suffix)].upper()
        f = wave.open(f[0], "rb")
        if f.getnchannels() != 1:
            print("Sorry - .wav file must be mono")
            sys.exit(1)
        if f.getsampwidth() != 2:
            print("Sorry - .wav file must be 16-bit")
            sys.exit(1)
        freq = f.getframerate()
        pcm16 = f.readframes(f.getnframes())
        (adpcm, _) = audioop.lin2adpcm(pcm16, f.getsampwidth(), (0,0))
        adpcm = adpcm[:len(adpcm) & ~7]
        da = array.array('B', [((ord(c) >> 4) | ((15 & ord(c)) << 4)) for c in adpcm])
        self.align(8)
        self.add(name, da.tostring())
        self.define(name + "_LENGTH", len(da))
        self.define(name + "_FREQ", freq)

    def error(self, suffix, f, **_):
        print('ERROR: cannot identify type of file "%s"' % f)
        print()
        print('recognized file types are:')
        for suffix,(_, doc) in sorted(self.handlers.items()):
            print('  %s   %s' % (suffix, doc))
        sys.exit(1)

    def addall(self):
        for a in self.args:
            a = a.split(',')
            f = []
            vars = {}
            for part in a:
                if '=' in part:
                    varval = part.split('=')
                    if len(varval) != 2:
                        print('ERROR: syntax error in asset specification "%s"' % setting)
                        sys.exit(1)
                    (var, val) = varval
                    vars[var] = val
                else:
                    f.append(part)
            suffix = f[0].split('.')[-1].lower()
            (handler, _) = self.handlers.get(suffix, (self.error, ''))
            handler(suffix, f, **vars)

usage = """\
usage: gd2asset <options> <assets>
       gd3asset <options> <assets>

  -3          target GD3 (FT810 series) - set by gd3asset
  -d          dither all pixel conversions
  -f <name>   output asset file (default is header file)
  -o <name>   output header file

If no output header file is given, then "default_assets.h" is used

Each asset is a filename, optionally followed by some var=val
assignments. For example:
  pic1.png                 image, format ARGB4
  pic2.jpg,format=L8       image, format L8
  serif.ttf,size=16        font, 16 pixels high

Options various file types:

jpg,png,bmp,gif:
 format   """ + ' '.join(formats) + """. Default ARGB4

ttf,otf
 size     height in pixels. Default 12
 format   """ + ' '.join(formats) + """. Default ARGB4
 firstchar  first ASCII code encoded. Default 32
 topchar  maximum ASCII code encoded. Default 127
 charset  set of characters to encode (overrides topchar)

wav
 (no options)

The assets are compiled into flash, or if the "-f" option is given
into a file. In this case the file should be copied to the
microSD card.
In either case, calling LOAD_ASSETS() from the program loads all
assets.
"""

if __name__ == '__main__':
    import sys, getopt
    try:
        optlist, args = getopt.getopt(sys.argv[1:], "3do:f:")
    except getopt.GetoptError:
        sys.stdout.write(usage)
        sys.exit(1)

    optdict = dict(optlist)
    if 'gd3' in sys.argv[0].lower():
        optdict['-3'] = ''
    GD2Assets(" ".join(sys.argv), optdict, args).make()
