#!/usr/bin/env python3

# Copyright 2019 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

from __future__ import print_function

import os
import os.path
import subprocess
import sys

THIS_DIR = os.path.dirname(__file__)
SRC_ROOT_DIR = os.path.abspath(os.path.join(THIS_DIR, os.pardir))


# In version 3.6 and newer, the subprocess.check_output() function needs to be
# passed an encoding type to return a string, otherwise it returns a bytes type.
def _run_command(command):
  if sys.version_info >= (3, 6):
    return subprocess.check_output(command, encoding="UTF-8")
  else:
    return subprocess.check_output(command)


class Formatter(object):
  "Formatter formats files of a particular type."

  def __init__(self, supported_extensions, cmd):
    """Creates a Formatter.

    supported_extensions is a list of extensions supported by this Formatter.
    cmd is the command used to format files with the file path appended.
    """
    self._ext = supported_extensions
    self._cmd = cmd
    self._checked = False

  def is_supported(self, filepath):
    "True if the specified filepath has a supported extension."
    _, ext = os.path.splitext(filepath)
    return ext in self._ext

  def format(self, abspath):
    """Try to format the file at the specified absolute path.

    Returns False in case of failure.
    True if success.
    """
    if not self._can_use_binary():
      return False
    cmd = self._cmd[:]
    cmd.append(abspath)
    print(" ".join(cmd))
    _run_command(cmd)
    return True

  def maybe_print_install_msg(self):
    """If the Formatter has been invoked but could not find the binary it

    needs, prompt the user to install the required binary.
    """
    # If _checked is set to True, that means the Formatter has been used at
    # least once.
    if not self._checked or self._can_use_bin:
      return
    print("Unable to format {} files. Try installing {}.".format(
        self._ext, self._cmd[0]))

  def _can_use_binary(self):
    "Check if the binary needed to run the formatter is available."
    # Check to see if this was cached.
    if self._checked:
      return self._can_use_bin
    self._checked = True

    # Check to see if the binary specified in the command can be executed.
    paths = os.getenv("PATH").split(":")
    binary = self._cmd[0]
    for path in paths + [SRC_ROOT_DIR]:
      bin_path = os.path.join(path, binary)
      if os.path.exists(bin_path) and os.access(bin_path, os.X_OK):
        self._can_use_bin = True
        return True

    self._can_use_bin = False
    return False


class FormattingSession(object):
  """FormattingSession holds the information regarding the formatting of many

   files.
  """

  def __init__(self, root_dir):
    self._formatters = [
        Formatter([".h", ".cc", ".proto"], [
            "clang-format", "-style=file", "-fallback-style=Google",
            "-sort-includes", "-i"
        ]),
        Formatter([".h"], ["./tools/style/check-header-guards.py", "--fix"]),
        Formatter([".go"], ["gofmt", "-w"]),
        Formatter([".gn", ".gni"], ["gn", "format", "--in-place"]),
        Formatter([".py"], ["pyformat", "-i"]),
    ]
    # _formatted is number of files that were succesfully formatted.
    self._formatted = 0
    # _failed is the number of files which we tried to format but could not.
    self._failed = 0
    # _skipped is the number of files which did not try to format either because
    # we don't know how to format them (unsupported format) or because they are
    # not tracked files.
    self._skipped = 0
    self._seen_filepaths = set()
    self._root_dir = root_dir

  def _format_file(self, filepath):
    "Attempt to format a file."
    # Skip duplicates.
    if filepath in self._seen_filepaths:
      return
    self._seen_filepaths.add(filepath)
    for formatter in self._formatters:
      if not formatter.is_supported(filepath):
        continue
      abspath = os.path.normpath(os.path.join(self._root_dir, filepath))
      if formatter.format(abspath):
        self._formatted += 1
      else:
        self._failed += 1
    self._skipped += 1

  def format_changed(self, changes):
    "Format the specified changed files. Leaves untracked files unchanged."
    files = set()
    for change in changes:
      op = change[0]
      filename = change[1]
      if filename in files:
        continue
      files.add(filename)
      # For renames, the new file name is the last element on the line.
      if "R" in op:
        filename = change[-1]

      # 'A' means added and 'M' means modified.
      if "A" in op or "M" in op:
        self._format_file(filename)
        continue
      self._skipped += 1

    for f in self._formatters:
      f.maybe_print_install_msg()
    print(("Formatted {} file(s), failed to format {} file(s) and skipped {}"
           " file(s).").format(self._formatted, self._failed, self._skipped))


def _git_status():
  "Get the files that are changed."
  status_str = _run_command(
      ["git", "status", "--ignored=no", "--ignore-submodules", "--porcelain"])
  return [
      l.split()
      for l in status_str.split("\n")
      if len(l.split()) >= 2 and not _ignored_file(l.split()[1])
  ]


def _git_show():
  "Get the files that changed in the last git commit."
  show_str = _run_command(
      ["git", "show", "--name-status", "--oneline", "--ignore-submodules"])
  lines = show_str.split("\n")
  return [
      l.split()
      for l in lines[1:]
      if len(l.split()) >= 2 and not _ignored_file(l.split()[1])
  ]


IGNORED_FILES = [
    "third_party",
    "build",
    "src/bin/config_parser/src/source_generator/source_generator_test_files",
    "src/pb/encrypted_message.proto",
    "src/pb/observation_batch.proto",
]


def _ignored_file(f):
  for name in IGNORED_FILES:
    if f.startswith(name):
      return True
  return False


def _git_ls_files():
  "Get all tracked files."
  ls_files_str = _run_command(["git", "ls-files"])
  return [["M", l] for l in ls_files_str.split("\n") if not _ignored_file(l)]


def _git_root_dir():
  "Get the root of the current git repository."
  root_dir = _run_command(["git", "rev-parse", "--show-toplevel"])
  return root_dir.strip()


def fmt(staged_only,
        also_fmt_last_commit,
        also_fmt_all_tracked,
        repo_path=None):
  """Format last changed files in a git repository.

  If staged_only is True, do not format any files that are not staged.
  If also_fmt_last_commit is True, also format files changes in the latest
  commit.
  If also_fmt_all_tracked is True, also format all tracked files.
  If repo_path is None, use the current git repository. If repo_path is not
  None, format files in that repository.
  """
  if not repo_path:
    repo_path = _git_root_dir()

  cwd = os.getcwd()
  repo_path = os.path.abspath(repo_path)
  try:
    os.chdir(repo_path)
    changes = _git_status()
    if not changes and not staged_only:
      changes += _git_show()
    if also_fmt_all_tracked:
      changes = _git_ls_files()
    if also_fmt_last_commit:
      changes += _git_show()
    session = FormattingSession(repo_path)
    session.format_changed(changes)
  finally:
    os.chdir(cwd)


if __name__ == "__main__":
  fmt(True, False)
