#!/usr/bin/env python
#
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Copies files to a directory."""

import itertools
import optparse
import os
import shutil
import sys

from util import build_utils


def _get_all_files(base):
  """Returns a list of all the files in |base|. Each entry is relative to the
  last path entry of |base|."""
  result = []
  dirname = os.path.dirname(base)
  for root, _, files in os.walk(base):
    result.extend([os.path.join(root[len(dirname):], f) for f in files])
  return result

def CopyFile(f, dest, deps):
  """Copy file or directory and update deps."""
  if os.path.isdir(f):
    shutil.copytree(f, os.path.join(dest, os.path.basename(f)))
    deps.extend(_get_all_files(f))
  else:
    shutil.copy(f, dest)
    deps.append(f)

def DoCopy(options, deps):
  """Copy files or directories given in options.files and update deps."""
  files = list(itertools.chain.from_iterable(build_utils.ParseGypList(f)
                                             for f in options.files))

  for f in files:
    if os.path.isdir(f) and not options.clear:
      print ('To avoid stale files you must use --clear when copying '
             'directories')
      sys.exit(-1)
    CopyFile(f, options.dest, deps)

def DoRenaming(options, deps):
  """Copy and rename files given in options.renaming_sources and update deps."""
  src_files = list(itertools.chain.from_iterable(
                   build_utils.ParseGypList(f)
                   for f in options.renaming_sources))

  dest_files = list(itertools.chain.from_iterable(
                    build_utils.ParseGypList(f)
                    for f in options.renaming_destinations))

  if (len(src_files) != len(dest_files)):
    print('Renaming source and destination files not match.')
    sys.exit(-1)

  for src, dest in itertools.izip(src_files, dest_files):
    if os.path.isdir(src):
      print ('renaming diretory is not supported.')
      sys.exit(-1)
    else:
      CopyFile(src, os.path.join(options.dest, dest), deps)

def main(args):
  args = build_utils.ExpandFileArgs(args)

  parser = optparse.OptionParser()
  build_utils.AddDepfileOption(parser)

  parser.add_option('--dest', help='Directory to copy files to.')
  parser.add_option('--files', action='append',
                    help='List of files to copy.')
  parser.add_option('--clear', action='store_true',
                    help='If set, the destination directory will be deleted '
                    'before copying files to it. This is highly recommended to '
                    'ensure that no stale files are left in the directory.')
  parser.add_option('--stamp', help='Path to touch on success.')
  parser.add_option('--renaming-sources',
                    action='append',
                    help='List of files need to be renamed while being '
                         'copied to dest directory')
  parser.add_option('--renaming-destinations',
                    action='append',
                    help='List of destination file name without path, the '
                         'number of elements must match rename-sources.')

  options, _ = parser.parse_args(args)

  if options.clear:
    build_utils.DeleteDirectory(options.dest)
    build_utils.MakeDirectory(options.dest)

  deps = []

  if options.files:
    DoCopy(options, deps)

  if options.renaming_sources:
    DoRenaming(options, deps)

  if options.depfile:
    build_utils.WriteDepfile(
        options.depfile,
        deps + build_utils.GetPythonDependencies())

  if options.stamp:
    build_utils.Touch(options.stamp)


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

