#!/usr/local/opt/python/bin/python3.7

import argparse
import macresources
import sys
import tempfile
from os import path

def fourcc(s):
    b = s.encode('mac_roman').ljust(4, b' ')
    if len(b) != 4:
        raise ValueError('wrong length')
    return b

def seemshex(s):
    s = s.lower()
    if not s: return False
    return all(c in '0123456789abcdef' for c in s)

def seemsdec(s):
    if not s: return False
    return all(c in '0123456789' for c in s)

def resid(s):
    s = s.lower()
    if s.startswith('0x') and seemshex(s[2:]):
        thenum = int(s[2:], 16)
        if thenum > 0x7fff: thenum -= 0x8000
    elif s.startswith('$') and seemshex(s[1:]):
        thenum = int(s[1:], 16)
        if thenum > 0x7fff: thenum -= 0x8000
    else:
        thenum = int(s)
    if not (-0x8000 <= thenum <= 0x7fff): raise ValueError
    return thenum

parser = argparse.ArgumentParser(description='''
    Copy a single MacOS resource from a source file to the standard
    output. If the source filename ends with `.r' or `.rdump', then it
    is parsed using the `SimpleRez' subset of the Rez language. TODO:
    find a way to specify null characters so that desk accessories can
    be looked up by name.
''')

parser.add_argument('srcfile', help='resource file or Rez file')
parser.add_argument('type', type=fourcc, help='four-byte type of resource (converted to Mac Roman pre-lookup)')
parser.add_argument('id', type=resid, help='ID number of resource (-32768 to 32767)')
parser.add_argument('-f', dest='tofile', action='store_true', help='copy to a tempfile instead')

args = parser.parse_args()

with open(args.srcfile, 'rb') as f:
    raw = f.read()

if args.srcfile.endswith('.r') or args.srcfile.endswith('.rdump'):
    resources = macresources.parse_rez_code(raw)
else:
    resources = macresources.parse_file(raw)

for r in resources:
    if r.type == args.type and r.id == args.id:
        myres = r
        break
else:
    raise ValueError(args.type, args.id)

if args.tofile:
    tmpname = '-%s-%s-%d' % (path.basename(args.srcfile), myres.type.decode('mac_roman'), myres.id)
    with tempfile.NamedTemporaryFile(suffix=tmpname, delete=False, mode='wb') as f:
        f.write(myres.data)
        print(f.name)
else:
    try:
        sys.stdout.buffer.write(myres.data)
    except BrokenPipeError:
        pass
