# Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
#
# This python script creates a tar archive and a C++ source file which contains
# the tar archive as an array of bytes.

import os
import sys
from os.path import join, splitext
import time
from optparse import OptionParser
from datetime import date
import tarfile
import tempfile

def makeArchive(tar_path, client_root, files):
  tar = tarfile.open(tar_path, mode='w')
  for input_file_name in files:
    # Chop off client_root.
    archive_file_name = input_file_name[ len(client_root) : ]
    # Open input file and add it to the archive.
    with open(input_file_name, 'rb') as input_file:
      tarInfo = tarfile.TarInfo(name=archive_file_name)
      input_file.seek(0,2)
      tarInfo.size = input_file.tell()
      input_file.seek(0)
      tar.addfile(tarInfo, fileobj=input_file)
  tar.close()

def writeCCFile(output_file,
                outer_namespace,
                inner_namespace,
                name,
                tar_archive,
                ):
  cc_text = '''
// Copyright (c) %d, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

''' % date.today().year
  cc_text += '''

#if defined(_WIN32)
typedef unsigned __int8 uint8_t;
#else
#include <inttypes.h>
#include <stdint.h>
#endif
#include <stddef.h>

'''
  cc_text += 'namespace %s {\n' % outer_namespace
  if inner_namespace != None:
    cc_text += 'namespace %s {\n' % inner_namespace
  cc_text += '\n\n'
  # Write the archive.
  cc_text += 'static const uint8_t %s_[] = {\n   ' % name
  lineCounter = 0
  for byte in tar_archive:
    cc_text += r" %d," % ord(byte)
    lineCounter += 1
    if lineCounter == 10:
      cc_text += '\n   '
      lineCounter = 0
  if lineCounter != 0:
    cc_text += '\n   '
  cc_text += '\n};\n'
  cc_text += '\nunsigned int %s_len = %d;\n' % (name, len(tar_archive))
  cc_text += '\nconst uint8_t* %s = %s_;\n\n' % (name, name)
  if inner_namespace != None:
    cc_text += '}  // namespace %s\n' % inner_namespace
  cc_text += '} // namespace %s\n' % outer_namespace

  open(output_file, 'w').write(cc_text)

def main(args):
  try:
    # Parse input.
    parser = OptionParser()
    parser.add_option("--output",
                      action="store", type="string",
                      help="output file name")
    parser.add_option("--tar_output",
                      action="store", type="string",
                      help="tar output file name")
    parser.add_option("--outer_namespace",
                      action="store", type="string",
                      help="outer C++ namespace",
                      default="dart")
    parser.add_option("--inner_namespace",
                      action="store", type="string",
                      help="inner C++ namespace",
                      default="bin")
    parser.add_option("--name",
                      action="store", type="string",
                      help="name of tar archive symbol")
    parser.add_option("--client_root",
                      action="store", type="string",
                      help="root directory client resources")

    (options, args) = parser.parse_args()
    if not options.output:
      sys.stderr.write('--output not specified\n')
      return -1
    if not options.tar_output:
      sys.stderr.write('--tar_output not specified\n')
      return -1
    if not options.name:
      sys.stderr.write('--name not specified\n')
      return -1
    if not options.client_root:
      sys.stderr.write('--client_root not specified')
      return -1

    files = [ ]

    for dirname, dirnames, filenames in os.walk(options.client_root):
      # strip out all dot files.
      filenames = [f for f in filenames if not f[0] == '.']
      dirnames[:] = [d for d in dirnames if not d[0] == '.']
      for f in filenames:
        src_path = os.path.join(dirname, f)
        if (os.path.isdir(src_path)):
            continue
        files.append(src_path)

    # Write out archive.
    makeArchive(options.tar_output, options.client_root, files)

    # Read it back in.
    with open(options.tar_output, 'rb') as tar_file:
      tar_archive = tar_file.read()

    # Write CC file.
    writeCCFile(options.output,
                options.outer_namespace,
                options.inner_namespace,
                options.name,
                tar_archive)
    return 0

  except Exception, inst:
    sys.stderr.write('create_resources.py exception\n')
    sys.stderr.write(str(inst))
    sys.stderr.write('\n')
    return -1

if __name__ == '__main__':
  sys.exit(main(sys.argv))
