#!/usr/bin/env python
# Copyright (c) 2017, 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.

import argparse
import gn_helpers
import os
import re
import shutil
import sys

def ParseArgs(args):
  args = args[1:]
  parser = argparse.ArgumentParser(
      description='A script to copy a file tree somewhere')

  parser.add_argument('--exclude_patterns', '-e',
      type=str,
      help='Patterns to exclude [passed to shutil.copytree]')
  parser.add_argument('--from', '-f',
      dest="copy_from",
      type=str,
      help='Source directory')
  parser.add_argument('--gn', '-g',
      dest='gn',
      default=False,
      action='store_true',
      help='Output for GN for multiple sources, but do not copy anything.')
  parser.add_argument('gn_paths',
      metavar='name path ignore_pattern',
      type=str,
      nargs='*',
      default=None,
      help='When --gn is given, the specification of source paths to list.')
  parser.add_argument('--to', '-t',
      type=str,
      help='Destination directory')

  return parser.parse_args(args)


def ValidateArgs(args):
  if args.gn:
    if args.exclude_patterns or args.copy_from or args.to:
      print ("--gn mode does not accept other switches")
      return False
    if not args.gn_paths:
      print ("--gn mode requires a list of source specifications")
      return False
    return True
  if not args.copy_from or not os.path.isdir(args.copy_from):
    print ("--from argument must refer to a directory")
    return False
  if not args.to:
    print ("--to is required")
    return False
  return True


def CopyTree(src, dst, ignore=None):
  names = os.listdir(src)
  if ignore is not None:
    ignored_names = ignore(src, names)
  else:
    ignored_names = set()

  if not os.path.exists(dst):
    os.makedirs(dst)
  errors = []
  for name in names:
    if name in ignored_names:
      continue
    srcname = os.path.join(src, name)
    dstname = os.path.join(dst, name)
    try:
      if os.path.isdir(srcname):
        CopyTree(srcname, dstname, ignore)
      else:
        shutil.copy(srcname, dstname)
    except (IOError, os.error) as why:
      errors.append((srcname, dstname, str(why)))
    # catch the Error from the recursive CopyTree so that we can
    # continue with other files
    except Exception as err:
      errors.extend(err.args[0])
  try:
    shutil.copystat(src, dst)
  except WindowsError:
    # can't copy file access times on Windows
    pass
  except OSError as why:
    errors.extend((src, dst, str(why)))
  if errors:
    raise Error(errors)


def ListTree(src, ignore=None):
  names = os.listdir(src)
  if ignore is not None:
    ignored_names = ignore(src, names)
  else:
    ignored_names = set()

  srcnames = []
  for name in names:
    if name in ignored_names:
      continue
    srcname = os.path.join(src, name)
    if os.path.isdir(srcname):
      srcnames.extend(ListTree(srcname, ignore))
    else:
      srcnames.append(srcname)
  return srcnames


# source_dirs is organized such that sources_dirs[n] is the path for the source
# directory, and source_dirs[n+1] is a list of ignore patterns.
def SourcesToGN(source_dirs):
  if len(source_dirs) % 2 != 0:
    print ("--gn list length should be a multiple of 2.")
    return False
  data = []
  for i in range(0, len(source_dirs), 2):
    path = source_dirs[i]
    ignores = source_dirs[i + 1]
    if ignores in ["{}"]:
      sources = ListTree(path)
    else:
      patterns = ignores.split(',')
      sources = ListTree(path, ignore=shutil.ignore_patterns(*patterns))
    data.append(sources)
  scope_data = {"sources": data}
  print (gn_helpers.ToGNString(scope_data))
  return True


def Main(argv):
  args = ParseArgs(argv)
  if not ValidateArgs(args):
    return -1

  if args.gn:
    SourcesToGN(args.gn_paths)
    return 0

  if args.exclude_patterns == None:
    CopyTree(args.copy_from, args.to)
  else:
    patterns = args.exclude_patterns.split(',')
    CopyTree(args.copy_from, args.to, ignore=shutil.ignore_patterns(*patterns))
  return 0


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