# Copyright 2014 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Presubmit script for files in chrome/browser/resources.

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

USE_PYTHON3 = True
ACTION_XML_PATH = '../../../tools/metrics/actions/actions.xml'
PRESUBMIT_VERSION = '2.0.0'


def InternalCheckUserActionUpdate(input_api, output_api, action_xml_path):
  """Checks if any new user action has been added."""
  if any('actions.xml' == input_api.os_path.basename(f) for f in
         input_api.change.LocalPaths()):
    # If actions.xml is already included in the changelist, the PRESUBMIT
    # for actions.xml will do a more complete presubmit check.
    return []

  file_filter = lambda f: f.LocalPath().endswith('.html')
  action_re = r'(^|\s+)metric\s*=\s*"([^ ]*)"'
  current_actions = None
  for f in input_api.AffectedFiles(file_filter=file_filter):
    for line_num, line in f.ChangedContents():
      match = input_api.re.search(action_re, line)
      if match:
        # Loads contents in tools/metrics/actions/actions.xml to memory. It's
        # loaded only once.
        if not current_actions:
          with open(action_xml_path, encoding='utf-8') as actions_f:
            current_actions = actions_f.read()

        metric_name = match.group(2)
        is_boolean = IsBoolean(f.NewContents(), metric_name, input_api)

        # Search for the matched user action name in |current_actions|.
        if not IsActionPresent(current_actions, metric_name, is_boolean):
          return [output_api.PresubmitPromptWarning(
            'File %s line %d: %s is missing in '
            'tools/metrics/actions/actions.xml. Please run '
            'tools/metrics/actions/extract_actions.py to update.'
            % (f.LocalPath(), line_num, metric_name), [])]
  return []


def CheckUserActionUpdate(input_api, output_api):
  return InternalCheckUserActionUpdate(input_api, output_api, ACTION_XML_PATH)


def IsActionPresent(current_actions, metric_name, is_boolean):
  """Checks if metric_name is defined in the actions file.

  Checks whether there's matching entries in an actions.xml file for the given
  |metric_name|, depending on whether it is a boolean action.

  Args:
    current_actions: The content of the actions.xml file.
    metric_name: The name for which the check should be done.
    is_boolean: Whether the action comes from a boolean control.
  """
  if not is_boolean:
    action = 'name="{0}"'.format(metric_name)
    return action in current_actions

  action_disabled = 'name="{0}_Disable"'.format(metric_name)
  action_enabled = 'name="{0}_Enable"'.format(metric_name)

  return (action_disabled in current_actions and
      action_enabled in current_actions)


def IsBoolean(new_content_lines, metric_name, input_api):
  """Check whether action defined in the changed code is boolean or not.

  Checks whether the action comes from boolean control based on the HTML
  elements attributes.

  Args:
    new_content_lines: List of changed lines.
    metric_name: The  name for which the check should be done.
  """
  new_content = '\n'.join(new_content_lines)

  html_element_re = r'<(.*?)(^|\s+)metric\s*=\s*"%s"(.*?)>' % (metric_name)
  type_re = (r'datatype\s*=\s*"boolean"|type\s*=\s*"checkbox"|'
      'type\s*=\s*"radio".*?value\s*=\s*("true"|"false")')

  match = input_api.re.search(html_element_re, new_content, input_api.re.DOTALL)
  return (match and
      any(input_api.re.search(type_re, match.group(i)) for i in (1, 3)))


def CheckHtml(input_api, output_api):
  return input_api.canned_checks.CheckLongLines(
      input_api, output_api, 80, lambda x: x.LocalPath().endswith('.html'))


def CheckSvgsOptimized(input_api, output_api):
  results = []
  try:
    import sys
    old_sys_path = sys.path[:]
    cwd = input_api.PresubmitLocalPath()
    sys.path += [input_api.os_path.join(cwd, '..', '..', '..', 'tools')]
    from resources import svgo_presubmit
    results += svgo_presubmit.CheckOptimized(input_api, output_api)
  finally:
    sys.path = old_sys_path
  return results


def _ImportWebDevStyle(input_api):
  try:
    import sys
    old_sys_path = sys.path[:]
    cwd = input_api.PresubmitLocalPath()
    sys.path += [input_api.os_path.join(cwd, '..', '..', '..', 'tools')]
    from web_dev_style import presubmit_support
  finally:
    sys.path = old_sys_path
  return presubmit_support


def CheckWebDevStyle(input_api, output_api):
  presubmit_support = _ImportWebDevStyle(input_api)
  return presubmit_support.CheckStyle(input_api, output_api)


def CheckNoNewJs(input_api, output_api):
  EXCLUDED_PATHS = [
    'chrome/browser/resources/.eslintrc',
    'chrome/browser/resources/about_sys/',
    'chrome/browser/resources/bluetooth_internals/',
    'chrome/browser/resources/chromeos/',
    'chrome/browser/resources/device_log_ui/',
    'chrome/browser/resources/explore_sites_internals/',
    'chrome/browser/resources/family_link_user_internals/',
    'chrome/browser/resources/feed_internals/',
    'chrome/browser/resources/gaia_auth_host/',
    'chrome/browser/resources/hangout_services/',
    'chrome/browser/resources/image_editor/',
    'chrome/browser/resources/identity_scope_approval_dialog/',
    'chrome/browser/resources/internals/lens/',
    'chrome/browser/resources/internals/notifications/',
    'chrome/browser/resources/internals/query_tiles/',
    'chrome/browser/resources/inspect/',
    'chrome/browser/resources/invalidations/',
    'chrome/browser/resources/nearby_internals/',
    'chrome/browser/resources/nearby_share/',
    'chrome/browser/resources/net_internals/',
    'chrome/browser/resources/network_speech_synthesis/',
    'chrome/browser/resources/new_tab_page/untrusted/',
    'chrome/browser/resources/ntp4/',
    'chrome/browser/resources/offline_pages/',
    'chrome/browser/resources/omnibox/',
    'chrome/browser/resources/settings/',
    'chrome/browser/resources/tools/',
    'chrome/browser/resources/video_tutorials/',
  ]

  normalized_excluded_paths = []
  for path in EXCLUDED_PATHS:
    normalized_excluded_paths.append(input_api.os_path.normpath(path))

  def excluded_path(f):
    for path in normalized_excluded_paths:
      if f.LocalPath().startswith(path):
        return True
    return False

  presubmit_support = _ImportWebDevStyle(input_api)
  return presubmit_support.DisallowNewJsFiles(input_api, output_api,
                                              lambda f: not excluded_path(f))

def CheckPatchFormatted(input_api, output_api):
  results = input_api.canned_checks.CheckPatchFormatted(input_api, output_api,
                                                         check_js=True)
  return results
