#!/usr/bin/env python
# Copyright (c) 2011, 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.
"""Used to merge and copy dart source files for deployment to AppEngine"""

import fileinput
import sys
import shutil
import os
import re
from os.path import abspath, basename, dirname, exists, isabs, join
from glob import glob

re_directive = re.compile(
    r'^(library|import|part|native|resource)\s+(.*);$')
re_comment = re.compile(
    r'^(///|/\*| \*).*$')

class Library(object):
  def __init__(self, name, imports, sources, natives, code, comment):
    self.name = name
    self.imports = imports
    self.sources = sources
    self.natives = natives
    self.code = code
    self.comment = comment

def parseLibrary(library):
  """ Parses a .dart source file that is the root of a library, and returns
      information about it: the name, the imports, included sources, and any
      code in the file.
  """
  libraryname = None
  imports = []
  sources = []
  natives = []
  inlinecode = []
  librarycomment = []
  if exists(library):
    # TODO(sigmund): stop parsing when import/source
    for line in fileinput.input(library):
      match = re_directive.match(line)
      if match:
        directive = match.group(1)
        if directive == 'library':
          assert libraryname is None
          libraryname = match.group(2)
        elif directive == 'part':
          suffix = match.group(2)
          if not suffix.startswith('of '):
            sources.append(match.group(2).strip('"\''))
        elif directive == 'import':
          imports.append(match.group(2))
        else:
          raise Exception('unknown directive %s in %s' % (directive, line))
      else:
        # Check for library comment.
        if not libraryname and re_comment.match(line):
          librarycomment.append(line)
        else:
          inlinecode.append(line)
    fileinput.close()
  return Library(libraryname, imports, sources, natives, inlinecode,
                 librarycomment)

def normjoin(*args):
  return os.path.normpath(os.path.join(*args))

def mergefiles(srcs, dstfile):
  for src in srcs:
    with open(src, 'r') as s:
      for line in s:
        if not line.startswith('part of '):
          dstfile.write(line)

def main(outdir = None, *inputs):
  if not outdir or not inputs:
    print "Usage: %s OUTDIR INPUTS" % args[0]
    print "  OUTDIR is the war directory to copy to"
    print "  INPUTS is a list of files or patterns used to specify the input"
    print "   .dart files"
    print "This script should be run from the client root directory."
    print "Files will be merged and copied to: OUTDIR/relative-path-of-file,"
    print "except for dart files with absolute paths, which will be copied to"
    print " OUTDIR/absolute-path-as-directories"
    return 1

  entry_libraries = []
  for i in inputs:
    entry_libraries.extend(glob(i))

  for entrypoint in entry_libraries:
    # Get the transitive set of dart files this entrypoint depends on, merging
    # each library along the way.
    worklist = [os.path.normpath(entrypoint)]
    seen = set()
    while len(worklist) > 0:
      lib = worklist.pop()
      if lib in seen:
        continue

      seen.add(lib)

      if (dirname(dirname(lib)).endswith('dom/generated/src')
          or dirname(lib).endswith('dom/src')):
        continue

      if lib.endswith('json/json.dart'):
        # TODO(jmesserly): Dartium interprets "json.dart" as "dart_json.dart",
        # so we need that add dart_json.dart here. This is hacky.
        lib = lib.replace('json.dart', 'dart_json.dart')

      library = parseLibrary(lib)

      # Ensure output directory exists
      outpath = join(outdir, lib[1:] if isabs(lib) else lib)
      dstpath = dirname(outpath)
      if not exists(dstpath):
        os.makedirs(dstpath)


      # Create file containing all imports, and inlining all sources
      with open(outpath, 'w') as f:
        if library.name:
          if library.comment:
            f.write('%s' % (''.join(library.comment)))
          f.write("library %s;\n\n" % library.name)
        else:
          f.write("library %s;\n\n" % basename(lib))
        for importfile in library.imports:
          f.write("import %s;\n" % (importfile))
        f.write('%s' % (''.join(library.code)))
        mergefiles([normjoin(dirname(lib), s) for s in library.sources], f)

      for suffix in library.imports:
        m = re.match(r'[\'"]([^\'"]+)[\'"](\s+as\s+\w+)?.*$', suffix)
        uri = m.group(1)
        if not uri.startswith('dart:'):
          worklist.append(normjoin(dirname(lib), uri));

  return 0

if __name__ == '__main__':
  sys.exit(main(*sys.argv[1:]))
