#!/usr/bin/env python

from s3o import S3O
from optparse import OptionParser
from glob import glob


def recursively_optimize_pieces(piece):
    optimize_piece(piece)
    for child in piece.children:
        optimize_piece(child)


def optimize_piece(piece):
    remap = {}
    new_indices = []
    for index in piece.indices:
        vertex = piece.vertices[index]
        if vertex not in remap:
            remap[vertex] = len(remap)
        new_indices.append(remap[vertex])

    new_vertices = [(index, vertex) for vertex, index in remap.items()]
    new_vertices.sort()
    new_vertices = [vertex for index, vertex in new_vertices]

    piece.indices = new_indices
    piece.vertices = new_vertices


if __name__ == '__main__':
    parser = OptionParser(usage="%prog [options] FILES", version="%prog 0.1",
                          description="Optimize a Spring S3O file by "
                                      "removing redundant data.")
    parser.add_option("-d", "--dry-run", action="store_true",
                      default=False, dest="is_dry",
                      help="show output summary without committing changes")
    parser.add_option("-q", "--quiet", action="store_true",
                      default=False, dest="silence_output",
                      help="silence optimization summary")

    options, args = parser.parse_args()
    if len(args) < 1:
        parser.error("insufficient arguments")

    dry = options.is_dry
    silence_output = options.silence_output

    if len(args) == 1:
        filenames = glob(args[0])
    else:
        filenames = args

    for filename in filenames:
        with open(filename, 'rb+') as input_file:
            data = input_file.read()
            model = S3O(data)
            recursively_optimize_pieces(model.root_piece)
            optimized_data = model.serialize()
            delta_size = len(optimized_data) - len(data)

            if not silence_output:
                print("modified %s: "
                      "size change: %d bytes" % (filename, delta_size))

            if not dry and delta_size < 0:
                input_file.seek(0)
                input_file.truncate()
                input_file.write(optimized_data)

@@ -193,32 +193,44 @@
 ildren:%0A        
+recursively_
 optimize_piece(c
@@ -227,16 +227,17 @@
 ze_piece
+s
 (child)%0A

Fix piece optimization going only 2 levels deep.