# Copyright (c) 2013, 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 string literals in a C++ source file from a C++
# source template and one or more resource files.

import os
import sys
from os.path import join, splitext
import time
from optparse import OptionParser
import re
from datetime import date
import zlib

def makeResources(root_dir, client_dir, input_files, table_name, compress, no_compress_extensions):
  result = ''
  resources = []

  # Write each file's contents as a byte string constant.
  for resource_file in input_files:
    if root_dir and resource_file.startswith(root_dir):
      resource_file_name = resource_file[ len(root_dir) : ]
    elif client_dir and resource_file.startswith(client_dir):
      resource_file_name = resource_file[ len(client_dir) : ]
    else:
      resource_file_name = resource_file
    _, ext = os.path.splitext(resource_file)
    if ext in no_compress_extensions:
      # Force no compression for files of this extension.
      compress = None
    resource_url = '/%s' % resource_file_name
    result += '// %s\n' % resource_file
    result += 'const char '
    resource_name = re.sub(r'(/|\.|-|\\)', '_', resource_file_name) + '_'
    result += resource_name
    result += '[] = {\n   '
    fileHandle = open(resource_file, 'rb')
    lineCounter = 0
    file_contents = fileHandle.read()
    if compress:
      file_contents = zlib.compress(file_contents)
    for byte in file_contents:
      result += r" '\x%02x'," % ord(byte)
      lineCounter += 1
      if lineCounter == 10:
        result += '\n   '
        lineCounter = 0
    if lineCounter != 0:
      result += '\n   '
    result += ' 0\n};\n\n'
    resource_url_scrubbed = re.sub(r'\\', '/', resource_url)
    resources.append(
        (resource_url_scrubbed, resource_name, len(file_contents)));

  # Write the resource table.
  result += 'ResourcesEntry __%s_resources_[] = ' % table_name
  result += '{\n'
  for res in resources:
    result += '   { "%s", %s, %d },\n' % res
  result += '   { 0, 0, 0 },\n'
  result += '};\n\n'
  return result


def makeFile(output_file, root_dir, client_dir, input_files, outer_namespace,
             inner_namespace, table_name, compress, no_compress_extensions):
  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 += 'namespace %s {\n' % outer_namespace
  if inner_namespace != None:
    cc_text += 'namespace %s {\n' % inner_namespace
  cc_text += '''
struct ResourcesEntry {
  const char* path_;
  const char* resource_;
  int length_;
};

'''
  cc_text += makeResources(root_dir, client_dir, input_files, table_name,
                           compress, no_compress_extensions)
  cc_text += '\n'
  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)
  return True


def main(args):
  try:
    # Parse input.
    parser = OptionParser()
    parser.add_option("--output",
                      action="store", type="string",
                      help="output file name")
    parser.add_option("--root_prefix",
                      action="store", type="string",
                      help="root directory for resources")
    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")
    parser.add_option("--table_name",
                      action="store", type="string",
                      help="name of table")
    parser.add_option("--client_root",
                      action="store", type="string",
                      help="root directory client resources")
    parser.add_option("--compress",
                      action="store_true",
                      help="zlib compress resources")
    parser.add_option("--no_compress_extensions",
                      action="append",
                      default=['.dart'],
                      help="file extensions that should not be compressed.")

    (options, args) = parser.parse_args()
    if not options.output:
      sys.stderr.write('--output not specified\n')
      return -1
    if not options.table_name:
      sys.stderr.write('--table_name not specified\n')
      return -1
    if len(args) == 0:
      sys.stderr.write('No input files specified\n')
      return -1

    files = [ ]

    if options.client_root != None:
      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
          # Skip devtools version
          if (src_path.find("index_devtools") != -1):
              continue
          files.append(src_path)

    for arg in args:
      files.append(arg)

    if not makeFile(options.output, options.root_prefix, options.client_root,
                    files, options.outer_namespace, options.inner_namespace,
                    options.table_name, options.compress,
                    options.no_compress_extensions):
      return -1

    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))
