#!/usr/bin/env python3
# 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):
    # Recursive helper method to collect errors but keep processing.
    def copy_tree(src, dst, ignore, errors):
        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)
        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):
                    copy_tree(srcname, dstname, ignore, errors)
                else:
                    shutil.copy(srcname, dstname)
            except (IOError, os.error) as why:
                errors.append((srcname, dstname, str(why)))
        try:
            shutil.copystat(src, dst)
        except WindowsError:
            # Can't copy file access times on Windows.
            pass
        except OSError as why:
            errors.append((src, dst, str(why)))

    # Format errors from file copies.
    def format_error(error):
        if len(error) == 1:
            return "Error: {msg}".format(msg=str(error[0]))
        return "From: {src}\nTo:   {dst}\n{msg}" \
                .format(src=error[0], dst=error[1], msg=error[2])

    errors = []
    copy_tree(src, dst, ignore, errors)
    if errors:
        failures = "\n\n".join(format_error(error) for error in errors)
        parts = ("Some file copies failed:", "=" * 78, failures)
        msg = '\n'.join(parts)
        raise RuntimeError(msg)


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