#
# Copyright 2021 Google LLC.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
"""Top-level presubmit script for libwebp2.

See https://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for
details on the presubmit API built into depot_tools.
"""

import re
import subprocess2

USE_PYTHON3 = True
_BASH_INDENTATION = "2"
_GIT_COMMIT_SUBJECT_LENGTH = 65
_INCLUDE_BASH_FILES_ONLY = [r".*\.sh$"]
_INCLUDE_MAN_FILES_ONLY = [r"man/.+\.1$"]
_LIBWEBP2_MAX_LINE_LENGTH = 80


def _CheckCommitSubjectLength(input_api, output_api):
  """Ensures commit's subject length is no longer than 65 chars."""
  name = "git-commit subject"
  cmd = ["git", "log", "-1", "--pretty=%s"]
  start = input_api.time.time()
  proc = subprocess2.Popen(
      cmd,
      stderr=subprocess2.PIPE,
      stdout=subprocess2.PIPE,
      universal_newlines=True)

  stdout, _ = proc.communicate()
  duration = input_api.time.time() - start

  if not re.match(r"^Revert",
                  stdout) and (len(stdout) - 1) > _GIT_COMMIT_SUBJECT_LENGTH:
    failure_msg = (
        "The commit subject: %s is too long (%d chars)\n"
        "Try to keep this to 50 or less.\n"
        "https://www.git-scm.com/book/en/v2/Distributed-Git-Contributing-to-a-"
        "Project#_commit_guidelines") % (stdout, len(stdout) - 1)
    return output_api.PresubmitError("%s\n (%4.2fs) failed\n%s" %
                                     (name, duration, failure_msg))

  return output_api.PresubmitResult("%s\n (%4.2fs) success" % (name, duration))


def _GetFilesToSkip(input_api):
  return list(input_api.DEFAULT_FILES_TO_SKIP) + [
      r"\.pylintrc$",
  ]


def _RunManCmd(input_api, output_api, man_file):
  cmd = ["man", "--warnings", "-EUTF-8", "-l", "-Tutf8", "-Z", man_file]
  name = "Check %s file." % man_file
  start = input_api.time.time()
  output, _ = subprocess2.communicate(
      cmd, stdout=None, stderr=subprocess2.PIPE, universal_newlines=True)
  duration = input_api.time.time() - start
  if output[1]:
    return output_api.PresubmitError("%s\n%s (%4.2fs) failed\n%s" %
                                     (name, " ".join(cmd), duration, output[1]))
  return output_api.PresubmitResult("%s\n%s (%4.2fs)\n" %
                                    (name, " ".join(cmd), duration))


def _RunShellCheckCmd(input_api, output_api, bash_file):
  """shellcheck command wrapper."""
  cmd = ["shellcheck", "-x", "-oall", "-sbash", bash_file]
  name = "Check %s file." % bash_file
  start = input_api.time.time()
  output, rc = subprocess2.communicate(
      cmd, stdout=None, stderr=subprocess2.PIPE, universal_newlines=True)
  duration = input_api.time.time() - start
  if rc == 0:
    return output_api.PresubmitResult("%s\n%s (%4.2fs)\n" %
                                      (name, " ".join(cmd), duration))
  return output_api.PresubmitError("%s\n%s (%4.2fs) failed\n%s" %
                                   (name, " ".join(cmd), duration, output[1]))


def _RunShfmtCheckCmd(input_api, output_api, bash_file):
  """shfmt command wrapper."""
  cmd = [
      "shfmt", "-i", _BASH_INDENTATION, "-bn", "-ci", "-sr", "-kp", "-d",
      bash_file
  ]
  name = "Check %s file." % bash_file
  start = input_api.time.time()
  output, rc = subprocess2.communicate(
      cmd, stdout=None, stderr=subprocess2.PIPE, universal_newlines=True)
  duration = input_api.time.time() - start
  if rc == 0:
    return output_api.PresubmitResult("%s\n%s (%4.2fs)\n" %
                                      (name, " ".join(cmd), duration))
  return output_api.PresubmitError("%s\n%s (%4.2fs) failed\n%s" %
                                   (name, " ".join(cmd), duration, output[1]))


def _RunCmdOnCheckedFiles(input_api, output_api, run_cmd, files_to_check):
  """Ensure that libwebp2/ files are clean."""
  file_filter = lambda x: input_api.FilterSourceFile(
      x, files_to_check=files_to_check, files_to_skip=None)

  affected_files = input_api.change.AffectedFiles(file_filter=file_filter)
  results = [
      run_cmd(input_api, output_api, f.AbsoluteLocalPath())
      for f in affected_files
  ]
  return results


def _CommonChecks(input_api, output_api):
  results = []
  results.extend(
      input_api.canned_checks.CheckChangeHasNoCrAndHasOnlyOneEol(
          input_api, output_api))
  results.extend(
      input_api.canned_checks.CheckChangeHasNoTabs(input_api, output_api))
  results.extend(
      input_api.canned_checks.CheckChangeHasNoStrayWhitespace(
          input_api, output_api))
  results.append(_CheckCommitSubjectLength(input_api, output_api))

  source_file_filter = lambda x: input_api.FilterSourceFile(
      x, files_to_skip=_GetFilesToSkip(input_api))
  results.extend(
      input_api.canned_checks.CheckLongLines(
          input_api,
          output_api,
          maxlen=_LIBWEBP2_MAX_LINE_LENGTH,
          source_file_filter=source_file_filter))

  results.extend(
      input_api.canned_checks.CheckPatchFormatted(
          input_api,
          output_api,
          check_clang_format=False,
          check_python=True,
          result_factory=output_api.PresubmitError))
  results.extend(
      _RunCmdOnCheckedFiles(input_api, output_api, _RunManCmd,
                            _INCLUDE_MAN_FILES_ONLY))
  # Run pylint.
  results.extend(
      input_api.canned_checks.RunPylint(
          input_api, output_api, pylintrc=".pylintrc", version="2.7"))

  # Binaries shellcheck and shfmt are not installed in depot_tools.
  # Installation is needed
  try:
    subprocess2.communicate(["shellcheck", "--version"])
    results.extend(
        _RunCmdOnCheckedFiles(input_api, output_api, _RunShellCheckCmd,
                              _INCLUDE_BASH_FILES_ONLY))
    print("shfmt")
    subprocess2.communicate(["shfmt", "-version"])
    results.extend(
        _RunCmdOnCheckedFiles(input_api, output_api, _RunShfmtCheckCmd,
                              _INCLUDE_BASH_FILES_ONLY))
  except OSError as os_error:
    results.append(
        output_api.PresubmitPromptWarning(
            "%s\nPlease install missing binaries locally." % os_error.args[0]))
  return results


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


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