# Copyright (C) 2014 Google Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
#     * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
#     * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""
DevTools presubmit script

See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
for more details about the presubmit API built into gcl.
"""

# pylint: skip-file

import sys

EXCLUSIVE_CHANGE_DIRECTORIES = [
    [ 'third_party', 'v8' ],
    [ 'node_modules' ],
    [ 'OWNERS' ],
]

def _CheckChangesAreExclusiveToDirectory(input_api, output_api):
    if input_api.change.DISABLE_THIRD_PARTY_CHECK != None:
        return []

    def IsParentDir(file, dir):
        while file != '':
            if file == dir:
                return True
            file = input_api.os_path.dirname(file)
        return False

    def FileIsInDir(file, dirs):
        for dir in dirs:
            if IsParentDir(file, dir):
                return True

    affected_files = input_api.LocalPaths()
    num_affected = len(affected_files)
    for dirs in EXCLUSIVE_CHANGE_DIRECTORIES:
        dir_list = ', '.join(dirs)
        affected_in_dir = filter(lambda f: FileIsInDir(f, dirs), affected_files)
        num_in_dir = len(affected_in_dir)
        if num_in_dir == 0:
            continue
        # Addition of new third_party folders must have a new entry in `.gitignore`
        if '.gitignore' in affected_files:
            num_in_dir = num_in_dir + 1
        if num_in_dir < num_affected:
            return [
                output_api
                .PresubmitError(('CLs that affect files in "%s" should be limited to these files/directories.' % dir_list) +
                                ' You can disable this check by adding DISABLE_THIRD_PARTY_CHECK=<reason> to your commit message')
            ]
    return []


def _CheckBuildGN(input_api, output_api):
    script_path = input_api.os_path.join(input_api.PresubmitLocalPath(), 'scripts', 'check_gn.js')
    return _checkWithNodeScript(input_api, output_api, script_path)


def _CheckFormat(input_api, output_api):

    def popen(args):
        return input_api.subprocess.Popen(args=args, stdout=input_api.subprocess.PIPE, stderr=input_api.subprocess.STDOUT)

    affected_files = _getAffectedJSFiles(input_api)
    if len(affected_files) == 0:
        return []
    original_sys_path = sys.path
    try:
        sys.path = sys.path + [input_api.os_path.join(input_api.PresubmitLocalPath(), 'scripts')]
        import devtools_paths
    finally:
        sys.path = original_sys_path

    ignore_files = []
    eslint_ignore_path = input_api.os_path.join(input_api.PresubmitLocalPath(), '.eslintignore')
    with open(eslint_ignore_path, 'r') as ignore_manifest:
        for line in ignore_manifest:
            ignore_files.append(input_api.os_path.normpath(line.strip()))
    formattable_files = [
        affected_file for affected_file in affected_files if all(ignore_file not in affected_file for ignore_file in ignore_files)
    ]
    if len(formattable_files) == 0:
        return []

    check_formatting_process = popen(['git', 'cl', 'format', '--js', '--dry-run'] + formattable_files)
    check_formatting_process.communicate()
    if check_formatting_process.returncode == 0:
        return []

    format_args = ['git', 'cl', 'format', '--js'] + formattable_files
    format_process = popen(format_args)
    format_out, _ = format_process.communicate()
    if format_process.returncode != 0:
        return [output_api.PresubmitError(format_out)]

    # Use eslint to autofix the braces.
    # Also fix semicolon to avoid confusing clang-format.
    eslint_process = popen(
        [devtools_paths.node_path(), devtools_paths.eslint_path(), '--config', '.eslintrc.js', '--fix'] + affected_files)
    eslint_process.communicate()

    # Need to run clang-format again to align the braces
    popen(format_args).communicate()

    return [
        output_api.PresubmitError('ERROR: Found formatting violations.\n'
                                  'Ran clang-format on diff\n'
                                  'Use git status to check the formatting changes'),
        output_api.PresubmitError(format_out),
    ]


def _CheckDevtoolsLocalization(input_api, output_api, check_all_files=False):  # pylint: disable=invalid-name
    devtools_root = input_api.PresubmitLocalPath()
    script_path = input_api.os_path.join(devtools_root, 'scripts', 'test', 'run_localization_check.py')
    if check_all_files == True:
        # Scan all files and fix any errors
        args = ['--autofix', '--all']
    else:
        devtools_front_end = input_api.os_path.join(devtools_root, 'front_end')
        affected_front_end_files = _getAffectedFiles(input_api, [devtools_front_end], ['D'],
                                                     ['.js', '.grdp', '.grd', 'module.json'])

        if len(affected_front_end_files) == 0:
            return []
        # Scan only added or modified files with specific extensions.
        args = [
            '--autofix',
            '--files',
        ] + affected_front_end_files
    process = input_api.subprocess.Popen(
        [input_api.python_executable, script_path] + args, stdout=input_api.subprocess.PIPE, stderr=input_api.subprocess.STDOUT)
    out, _ = process.communicate()
    if process.returncode != 0:
        return [output_api.PresubmitError(out)]
    return [output_api.PresubmitNotifyResult(out)]


def _CheckDevtoolsStyle(input_api, output_api):
    lint_path = input_api.os_path.join(input_api.PresubmitLocalPath(), 'scripts', 'test', 'run_lint_check.py')
    process = input_api.subprocess.Popen([input_api.python_executable, lint_path],
                                         stdout=input_api.subprocess.PIPE,
                                         stderr=input_api.subprocess.STDOUT)
    out, _ = process.communicate()
    if process.returncode != 0:
        return [output_api.PresubmitError(out)]
    return [output_api.PresubmitNotifyResult(out)]


def _CheckOptimizeSVGHashes(input_api, output_api):
    if not input_api.platform.startswith('linux'):
        return []

    original_sys_path = sys.path
    try:
        sys.path = sys.path + [input_api.os_path.join(input_api.PresubmitLocalPath(), 'scripts', 'build')]
        import devtools_file_hashes
    finally:
        sys.path = original_sys_path

    absolute_local_paths = [af.AbsoluteLocalPath() for af in input_api.AffectedFiles(include_deletes=False)]
    images_src_path = input_api.os_path.join('devtools', 'front_end', 'Images', 'src')
    image_source_file_paths = [path for path in absolute_local_paths if images_src_path in path and path.endswith('.svg')]
    image_sources_path = input_api.os_path.join(input_api.PresubmitLocalPath(), 'front_end', 'Images', 'src')
    hashes_file_name = 'optimize_svg.hashes'
    hashes_file_path = input_api.os_path.join(image_sources_path, hashes_file_name)
    invalid_hash_file_paths = devtools_file_hashes.files_with_invalid_hashes(hashes_file_path, image_source_file_paths)
    if len(invalid_hash_file_paths) == 0:
        return []
    invalid_hash_file_names = [input_api.os_path.basename(file_path) for file_path in invalid_hash_file_paths]
    file_paths_str = ', '.join(invalid_hash_file_names)
    error_message = 'The following SVG files should be optimized using optimize_svg_images script before uploading: \n  - %s' % file_paths_str
    return [output_api.PresubmitError(error_message)]


def _CheckCSSViolations(input_api, output_api):
    results = []
    for f in input_api.AffectedFiles(include_deletes=False):
        if not f.LocalPath().endswith('.css'):
            continue
        for line_number, line in f.ChangedContents():
            if '/deep/' in line:
                results.append(output_api.PresubmitError(('%s:%d uses /deep/ selector') % (f.LocalPath(), line_number)))
            if '::shadow' in line:
                results.append(output_api.PresubmitError(('%s:%d uses ::shadow selector') % (f.LocalPath(), line_number)))
    return results


def _CommonChecks(input_api, output_api):
    """Checks common to both upload and commit."""
    results = []
    # Cobalt changes don't need DevTools owners to be involved
    # results.extend(input_api.canned_checks.CheckOwnersFormat(input_api,
    #                                                          output_api))
    # results.extend(input_api.canned_checks.CheckOwners(input_api, output_api))
    results.extend(input_api.canned_checks.CheckChangeHasNoCrAndHasOnlyOneEol(input_api, output_api))
    results.extend(input_api.canned_checks.CheckChangeHasNoStrayWhitespace(input_api, output_api))
    # Cobalt's depot_tools doesn't include CheckGenderNeutral
    # results.extend(input_api.canned_checks.CheckGenderNeutral(input_api,
    #                                                           output_api))
    return results


def CheckChangeOnUpload(input_api, output_api):
    results = []
    results.extend(_CommonChecks(input_api, output_api))

    # Cobalt doesn't use GN to build.
    # results.extend(_CheckBuildGN(input_api, output_api))

    # Formatting & style checks use eslint from a Node install, which isn't
    # part of the Cobalt dev environment.
    # results.extend(_CheckFormat(input_api, output_api))
    # results.extend(_CheckDevtoolsStyle(input_api, output_api))

    results.extend(_CheckOptimizeSVGHashes(input_api, output_api))
    results.extend(_CheckCSSViolations(input_api, output_api))
    #results.extend(_CheckDevtoolsLocalization(input_api, output_api))
    results.extend(_CheckChangesAreExclusiveToDirectory(input_api, output_api))
    return results


def CheckChangeOnCommit(input_api, output_api):
    results = []
    results.extend(_CommonChecks(input_api, output_api))
    #results.extend(_CheckDevtoolsLocalization(input_api, output_api, True))
    results.extend(_CheckChangesAreExclusiveToDirectory(input_api, output_api))
    results.extend(input_api.canned_checks.CheckChangeHasDescription(input_api, output_api))
    return results


def _getAffectedFiles(input_api, parent_directories, excluded_actions, accepted_endings):  # pylint: disable=invalid-name
    """Return absolute file paths of affected files (not due to an excluded action)
       under a parent directory with an accepted file ending.
    """
    local_paths = [
        f.AbsoluteLocalPath() for f in input_api.AffectedFiles() if all(f.Action() != action for action in excluded_actions)
    ]
    affected_files = [
        file_name for file_name in local_paths
        if any(parent_directory in file_name for parent_directory in parent_directories) and any(
            file_name.endswith(accepted_ending) for accepted_ending in accepted_endings)
    ]
    return affected_files


def _getAffectedFrontEndFiles(input_api):
    devtools_root = input_api.PresubmitLocalPath()
    devtools_front_end = input_api.os_path.join(devtools_root, 'front_end')
    affected_front_end_files = _getAffectedFiles(input_api, [devtools_front_end], ['D'], ['.js'])
    return [input_api.os_path.relpath(file_name, devtools_root) for file_name in affected_front_end_files]


def _getAffectedJSFiles(input_api):
    devtools_root = input_api.PresubmitLocalPath()
    devtools_front_end = input_api.os_path.join(devtools_root, 'front_end')
    devtools_scripts = input_api.os_path.join(devtools_root, 'scripts')
    affected_js_files = _getAffectedFiles(input_api, [devtools_front_end, devtools_scripts], ['D'], ['.js'])
    return [input_api.os_path.relpath(file_name, devtools_root) for file_name in affected_js_files]


def _checkWithNodeScript(input_api, output_api, script_path, script_arguments=None):  # pylint: disable=invalid-name
    original_sys_path = sys.path
    try:
        sys.path = sys.path + [input_api.os_path.join(input_api.PresubmitLocalPath(), 'scripts')]
        import devtools_paths
    finally:
        sys.path = original_sys_path

    node_path = devtools_paths.node_path()

    if script_arguments is None:
        script_arguments = []

    process = input_api.subprocess.Popen(
        [node_path, script_path] + script_arguments, stdout=input_api.subprocess.PIPE, stderr=input_api.subprocess.STDOUT)
    out, _ = process.communicate()

    if process.returncode != 0:
        return [output_api.PresubmitError(out)]
    return [output_api.PresubmitNotifyResult(out)]
