#!/usr/bin/python

from __future__ import print_function

import sys, os, argparse

from s3turbo.S3Image import S3Image
from s3turbo.S3Turbo import S3Exception

def read(args):
    if args.log: logfile = open(args.log,"w")
    exitstatus = 0
    for fn in args.input_files:
        if not os.path.exists(fn):
            print("Could not open file '%s'" % fn)
            exitstatus = 1
            continue
        try:
            sf = S3Image(debug=args.verbose)
            sf.read_from_file(fn,compatibilityMode=args.compatible)
            if args.dumpfile:
                f = sf.find_file(args.dumpfile)
                if not f:
                    print("Could not find '%s'" % args.dumpfile)
                    continue
                buf = sf.read_file(f)
                sys.stdout.write(buf)
            if args.contents:
                sf.dump_contents()
            if args.props:
                sf.dump_props()
            if args.fat:
                sf.dump_fat()
            if args.test:
                sf.test_file(fn)
            if args.extract:
                sf.extract_all(args.extract,compatibilityMode=args.compatible)
        except IOError, e:
            if args.backtrace:
                print("Error in %s:" % repr(fn))
                raise
            exitstatus = 1
            if errno == 32: break
            else: raise
        except Exception, e:
            if args.backtrace:
                print("ERROR in %s:" % repr(fn))
                raise
            exitstatus = 1
            print("ERROR in %s:\n %s" % (repr(fn),str(e)), file=sys.stderr)
            if args.log:
                print(fn,file=logfile)
            if not args.keep_going:
                break
    return exitstatus

def write(args):
    exitstatus = 0
    try:
        sr = S3Image(debug=args.verbose)
        if args.name: sr.set_volname(args.name)
        if args.file: sr.read_from_file(args.file)
        else:
            sr.set_voldate()
            sr.set_voltime()
        if args.add:
            sr.add_directory(args.add)
        if args.oemname:
            sr.set_oemname(args.oemname)
        sr.write_to_file(args.output_file)
    except Exception, e:
        if args.backtrace:
            print("ERROR in %s:" % repr(args.file))
            raise
        exitstatus = 1
        print("ERROR in %s:\n %s" % (repr(args.file),str(e)), file=sys.stderr)
    return exitstatus

def main():
    parser = argparse.ArgumentParser(
        description='Process GEM S2/S3 image files')
    subparsers = parser.add_subparsers(
        help='sub-command help')
    readparser = subparsers.add_parser(
        'read',
        description='Read GEM S2/S3 image files')
    readparser.add_argument('input_files', type=str, nargs='+',
                            help='input files')
    readparser.add_argument('--compatible', action='store_true',
                            help='treat some errors as warnings')
    readparser.add_argument('-b', '--backtrace', action='store_true',
                            help='print backtrace instead of error message')
    readparser.add_argument('-c', '--contents', action='store_true',
                            help='dump list of image contents')
    readparser.add_argument('-d', '--dumpfile', metavar='FILE', type=str,
                            help='dump FILE to stdout')
    readparser.add_argument('-e', '--extract', metavar='DIR', type=str,
                            help='extract image to DIR')
    readparser.add_argument('-f', '--fat', action='store_true',
                            help='dump FAT of image file')
    readparser.add_argument('-k', '--keep-going', action='store_true',
                            help='continue processing files on error')
    readparser.add_argument('-l', '--log', metavar='FILE', type=str, nargs='?',
                            const='log.txt',
                            help='log problematic files to FILE')
    readparser.add_argument('-p', '--props', action='store_true',
                            help='dump image file properties')
    readparser.add_argument('-t', '--test', action='store_true',
                            help='test input file')
    readparser.add_argument('-v', '--verbose', action='store_true',
                            help='print debugging information')
    readparser.set_defaults(func=read)

    writeparser = subparsers.add_parser(
        'write',
        description='Write GEM S2/S3 image files')
    writeparser.add_argument('output_file', type=str, help='output file')
    writeparser.add_argument('--compatible', action='store_true',
                             help='treat some errors as warnings')
    writeparser.add_argument('-a', '--add', metavar='DIR', type=str,
                             help='add DIR to image')
    writeparser.add_argument('-b', '--backtrace', action='store_true',
                             help='print backtrace instead of error message')
    writeparser.add_argument('-f', '--file', type=str,
                             help='read input file')
    writeparser.add_argument('-n', '--name', type=str,
                             help='set volume name')
    writeparser.add_argument('-o', '--oemname', type=eval,
                             help='set oem name as python expression,'
                             ' e.g. "\'\\x20\\x20\\x20\\x20\\x20\\x00\\x0a\\x1b\'"')
    writeparser.add_argument('-v', '--verbose', action='store_true',
                             help='print debugging information')
    writeparser.set_defaults(func=write)
    
    args = parser.parse_args()
    exitstatus = args.func(args)

    # close stdout and stderr manually in order to avoid error messages
    # when piping
    sys.stderr.close()
    sys.stdout.close()
    sys.exit(exitstatus)

if __name__ == "__main__":
    main()
