#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright 2017 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Linter for various README.md files."""

from __future__ import print_function

import difflib
import os
import re
import sys

TOP_DIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))

# Find chromite!
sys.path.insert(0, os.path.join(TOP_DIR, '..', '..'))

from chromite.lib import commandline
from chromite.lib import git
from chromite.lib import cros_logging as logging
from chromite.lib import osutils


def GetActiveProjects():
  """Return the list of active projects."""
  # Look at all the paths (files & dirs) in the top of the git repo.  This way
  # we ignore local directories devs created that aren't actually committed.
  cmd = ['ls-tree', '--name-only', '-z', 'HEAD']
  result = git.RunGit(TOP_DIR, cmd)

  # Split the output on NULs to avoid whitespace/etc... issues.
  paths = result.stdout.split('\0')

  # ls-tree -z will include a trailing NUL on all entries, not just seperation,
  # so filter it out if found (in case ls-tree behavior changes on us).
  for path in [x for x in paths if x]:
    if os.path.isdir(os.path.join(TOP_DIR, path)):
      yield path


def CheckTopLevel():
  """Check the top level README.md list."""
  ret = 0
  path = os.path.join(TOP_DIR, 'README.md')
  data = osutils.ReadFile(path).splitlines()

  # Look for the directory header.
  try:
    i = data.index('# Local Project Directory')
  except ValueError:
    logging.error('README.md index out of sync')
    return 1
  data = data[i + 1:]

  # Pull out all the linked projects.
  listed_projs = []
  listed_dirs = []
  for line in data:
    # Break once we hit the end of the table.
    if line.startswith('#'):
      break

    m = re.match(r'^[|] \[([^]]+)*\]\(\./([^)]*)/\)', line)
    if m:
      listed_projs.append(m.group(1))
      listed_dirs.append(m.group(2))
  logging.debug('README.md projects: %s', listed_projs)

  sorted_projs = sorted(listed_projs)
  if listed_projs != sorted_projs:
    ret = 1
    lines = list(difflib.unified_diff(listed_projs, sorted_projs, lineterm=''))
    logging.error('README.md project listing should be kept sorted:\n%s',
                  '\n'.join(lines[2:]))

  # Check the list in README.md for outdated entries.
  old_dirs = []
  for project_dir in listed_dirs:
    path = os.path.join(TOP_DIR, project_dir)
    if not os.path.isdir(path):
      old_dirs.append(path)
  if old_dirs:
    ret = 1
    logging.error('README.md: found stale project entries: %s', old_dirs)

  # Check the local source repo for missing entries.
  existing_projs = sorted(GetActiveProjects())
  logging.debug('Found active projects: %s', existing_projs)
  new_projs = []
  for proj in existing_projs:
    path = os.path.join(TOP_DIR, proj)
    if os.path.isdir(path) and proj not in listed_projs:
      new_projs.append(proj)
  if new_projs:
    ret = 1
    logging.error('README.md: document new projects: %s', new_projs)

  return ret


def CheckSubdirs():
  """Check the subdir README.md files exist."""
  # Legacy projects that don't have a README.md file.
  # Someone should write some docs :D.
  LEGACYLIST = (
      'attestation',
      'avtest_label_detect',
      'buffet',
      'cros-disks',
      'fitpicker',
      'image-burner',
      'init',
      'libchromeos-ui',
      'libcontainer',
      'lorgnette',
      'modem-utilities',
      'mtpd',
      'salsa',
      'thd',
      'timberslide',
      'tpm_manager',
      'trim',
      'userfeedback',
      'userspace_touchpad',
      'vpn-manager',
  )

  ret = 0
  for proj in GetActiveProjects():
    readme = os.path.join(TOP_DIR, proj, 'README.md')
    if os.path.exists(readme):
      if proj in LEGACYLIST:
        logging.error(
            '*** Project "%s" is in no-README LEGACYLIST, but actually has '
            'one. Please remove it from LEGACYLIST!', proj)
    else:
      if not proj in LEGACYLIST:
        logging.error('*** Project "%s" needs a README.md file', proj)
        ret = 1
  return ret


def GetParser():
  """Return an argument parser."""
  parser = commandline.ArgumentParser(description=__doc__)
  parser.add_argument('--extensions', default='gyp,gypi',
                      help='Comma delimited file extensions to check. '
                           '(default: %(default)s)')
  parser.add_argument('files', nargs='*',
                      help='Files to run lint.')
  return parser


def main(argv):
  parser = GetParser()
  opts = parser.parse_args(argv)
  opts.Freeze()

  return CheckTopLevel() | CheckSubdirs()


if __name__ == '__main__':
  commandline.ScriptWrapperMain(lambda _: main)
