#!/usr/bin/env python

"""
usage: katana --expand-scene <filename> <outputdir>
       katana --archive-scene <inputdir> <filename>

Expand a 2.1+ katana file (tar format) to a directory containing scene xml
and opaque data files.  The output will go to outputdir.  If outputdir
does not exist, it will be created.  If outputdir exists and is not empty,
the expansion will fail.  The input file to read is specified with filename.

or

Archive a 2.1+ directory constaining scene xml and opaque data files.  

Remember that the first line of a Katana file is always text,
so "head -1" on the command line can show you the vital stats
of any Katana file.
"""

# This can be done without any Katana code.
# Going with that route, since it is quicker and cleaner
# startup. But that requires a little code dupe.
import cStringIO
import os
import sys
import tarfile
import zlib

import PyXmlIO

# Using PyXmlIO
# Some code duped from NodegraphGlobals._LoadXmlFromStream
def ExpandScene(filename, outputdir):

    # Check katana file header
    stream = open(filename, "rb")
    firstLine = stream.readline()
    firstTag = firstLine.strip()
    if firstTag[:8].lower() != "<katana ":
        raise ValueError("Not a valid Katana file")

    katanaElement = PyXmlIO.Parser().parseString(firstTag + "</katana>")
    
    if not katanaElement.hasAttr("archive"):
        raise ValueError("Katana file is not in archive format.  Use --printxml.")

    archiveAttr = katanaElement.getAttr("archive")
    if archiveAttr != "tar":
        raise ValueError("Unknown archive format.")

    # Check / create output directory
    if os.path.exists(outputdir):
        if not os.path.isdir(outputdir):
            raise RuntimeError(
                "Could not expand scene: '%s' exists and is not a directory." % (outputdir))

        if len(os.listdir(outputdir)) > 0:
            raise RuntimeError(
                "Could not expand scene: '%s' directory exists and is not empty." % (outputdir))
    else:
        try:
            os.makedirs(outputdir)
        except Exception, e:
            raise RuntimeError(
                "Could not expand scene: Error creating '%s' directory." % (outputdir))

    # Extract the files
    tar = tarfile.open(mode='r|gz', fileobj=stream)
    tar.extractall(outputdir)
    tar.close()

    # Write katana tag to extra file
    tagfile = open(os.path.join(outputdir, 'header.txt'), 'w')
    tagfile.write(firstTag)
    tagfile.close()


def ArchiveScene(inputdir, filename):

    # Check katana file header
    tagfile = open(os.path.join(inputdir, 'header.txt'), 'r')
    firstLine = tagfile.readline()
    firstTag = firstLine.strip()
    if firstTag[:8].lower() != "<katana ":
        raise ValueError("Not a valid Katana file")

    katanaElement = PyXmlIO.Parser().parseString(firstTag + "</katana>")
    katanaTag = katanaElement.writeString().replace("/>", ">").strip() + "\n"

    outStyle = PyXmlIO.OutputStyles()

    stream = open(filename, 'wb')
    stream.write(katanaTag)

    tar = tarfile.open(mode='w|gz', fileobj=stream)

    # make sure scene.katana appears in tar file first
    tar.add(os.path.join(inputdir, 'scene', 'scene.katana'), 'scene/scene.katana')
    for x in os.listdir(os.path.join(inputdir, 'scene')):
        filename = os.path.join('scene', os.path.basename(x))
        if filename != os.path.join('scene', 'scene.katana'):
            tar.add(os.path.join(inputdir, filename), filename, True)
    tar.close()

if __name__ == "__main__":
    if len(sys.argv) != 4 or sys.argv[1] not in ('expand', 'archive'):
        print __doc__
        sys.exit(1)

    try:
        if sys.argv[1] == 'expand':
            ExpandScene(sys.argv[2], sys.argv[3])
        elif sys.argv[1] == 'archive':
            ArchiveScene(sys.argv[2], sys.argv[3])
    except Exception, e:
        print e
        sys.exit(1)
