#!/usr/bin/python

"""Creates a CustomObject from a level."""


import os
import sys
import argparse

from distance.level import Level
from distance.bytes import DstBytes
from distance.printing import PrintContext


def iter_objects(source, recurse=-1):
    for obj in source:
        yield obj
        if recurse != 0 and obj.is_object_group:
            yield from iter_objects(obj.children, recurse=recurse-1)


def select_candidates(source, objnum, maxrecurse):
    res = []
    for i, obj in enumerate(iter_objects(source, maxrecurse)):
        if objnum is None or i == objnum:
            res.append(obj)
    return res


def main():
    parser = argparse.ArgumentParser(
        description=__doc__)
    parser.add_argument("-f", "--force", action='store_true',
                        help="Allow overwriting OUT file.")
    parser.add_argument("-n", "--objnum", type=int,
                        help="Object number to extract.")
    parser.add_argument("-l", "--maxrecurse", type=int, default=-1,
                        help="Maximum of recursions. 0 only lists layer objects.")
    parser.add_argument("IN",
                        help="Level .bytes filename.")
    parser.add_argument("OUT",
                        help="output .bytes filename.")
    args = parser.parse_args()

    objnum = args.objnum or None

    maxrecurse = args.maxrecurse

    write_mode = 'xb'
    if args.force:
        write_mode = 'wb'

    if not args.force and os.path.exists(args.OUT):
        print("file {args.OUT} exists. pass -f to force.", file=sys.stderr)
        return 1

    with open(args.IN, 'rb') as in_f:
        level = Level(DstBytes(in_f))
        candidates = select_candidates(level.iter_objects(), objnum, maxrecurse)

        tosave = None
        if len(candidates) == 1:
            tosave = candidates[0]
        elif len(candidates) > 1:
            p = PrintContext(file=sys.stdout, flags=('groups', 'subobjects'))
            p(f"Candidates: {len(candidates)}")
            with p.tree_children():
                for i, obj in enumerate(candidates):
                    p.tree_next_child()
                    p(f"Candidate: {i}")
                    p.print_data_of(obj)

        if tosave is not None:
            with open(args.OUT, write_mode) as out_f:
                tosave.print_data(file=sys.stdout, flags=('groups', 'subobjects'))
                dbytes = DstBytes(out_f)
                tosave.write(dbytes)
                print(f"{dbytes.pos} bytes written")
                return 0

    print("no matching object found", file=sys.stderr)
    return 1


if __name__ == '__main__':
    exit(main())


# vim:set sw=4 ts=8 sts=4 et sr ft=python fdm=marker tw=0:

@@ -93,16 +93,26 @@
 argparse
+%0Aimport re
 %0A%0Afrom d
@@ -452,28 +452,340 @@
 ce, 
-objnum, maxrecurse):
+args):%0A    objnum = args.objnum or None%0A%0A    maxrecurse = args.maxrecurse%0A%0A    type_patterns = %5Bre.compile(r) for r in args.type%5D%0A%0A    def match_object(obj):%0A        if type_patterns:%0A            typename = obj.type%0A            if not any(r.search(typename) for r in type_patterns):%0A                return False%0A        return True%0A
 %0A   
@@ -822,16 +822,31 @@
 umerate(
+obj for obj in 
 iter_obj
@@ -869,16 +869,65 @@
 recurse)
+%0A                            if match_object(obj)
 ):%0A     
@@ -1466,24 +1466,152 @@
  objects.%22)%0A
+    parser.add_argument(%22-t%22, %22--type%22, action='append', default=%5B%5D,%0A                        help=%22Match object type (regex).%22)%0A
     parser.a
@@ -1806,76 +1806,8 @@
 ()%0A%0A
-    objnum = args.objnum or None%0A%0A    maxrecurse = args.maxrecurse%0A%0A
     
@@ -2157,26 +2157,12 @@
 (), 
-objnum, maxrecurse
+args
 )%0A%0A 
@@ -2620,16 +2620,93 @@
 _of(obj)
+%0A        else:%0A            print(%22no matching object found%22, file=sys.stderr)
 %0A%0A      
@@ -3028,63 +3028,8 @@
  0%0A%0A
-    print(%22no matching object found%22, file=sys.stderr)%0A
     

allow filtering objects by type