# Copyright 2015 Google Inc. All Rights Reserved.
#
# 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
#
#     http://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.
"""Interface to file resources.

This module provides functions for interfacing with files: opening, writing, and
querying.
"""

import fnmatch
import os
import re

from lib2to3.pgen2 import tokenize

from yapf.yapflib import errors
from yapf.yapflib import py3compat
from yapf.yapflib import style

CR = '\r'
LF = '\n'
CRLF = '\r\n'


def GetDefaultStyleForDir(dirname):
  """Return default style name for a given directory.

  Looks for .style.yapf or setup.cfg in the parent directories.

  Arguments:
    dirname: (unicode) The name of the directory.

  Returns:
    The filename if found, otherwise return the global default (pep8).
  """
  dirname = os.path.abspath(dirname)
  while True:
    # See if we have a .style.yapf file.
    style_file = os.path.join(dirname, style.LOCAL_STYLE)
    if os.path.exists(style_file):
      return style_file

    # See if we have a setup.cfg file with a '[yapf]' section.
    config_file = os.path.join(dirname, style.SETUP_CONFIG)
    if os.path.exists(config_file):
      with open(config_file) as fd:
        config = py3compat.ConfigParser()
        config.read_file(fd)
        if config.has_section('yapf'):
          return config_file

    dirname = os.path.dirname(dirname)
    if (not dirname or not os.path.basename(dirname) or
        dirname == os.path.abspath(os.path.sep)):
      break

  global_file = os.path.expanduser(style.GLOBAL_STYLE)
  if os.path.exists(global_file):
    return global_file

  return style.DEFAULT_STYLE


def GetCommandLineFiles(command_line_file_list, recursive, exclude):
  """Return the list of files specified on the command line."""
  return _FindPythonFiles(command_line_file_list, recursive, exclude)


def WriteReformattedCode(filename,
                         reformatted_code,
                         encoding='',
                         in_place=False):
  """Emit the reformatted code.

  Write the reformatted code into the file, if in_place is True. Otherwise,
  write to stdout.

  Arguments:
    filename: (unicode) The name of the unformatted file.
    reformatted_code: (unicode) The reformatted code.
    encoding: (unicode) The encoding of the file.
    in_place: (bool) If True, then write the reformatted code to the file.
  """
  if in_place:
    with py3compat.open_with_encoding(
        filename, mode='w', encoding=encoding, newline='') as fd:
      fd.write(reformatted_code)
  else:
    py3compat.EncodeAndWriteToStdout(reformatted_code)


def LineEnding(lines):
  """Retrieve the line ending of the original source."""
  endings = {CRLF: 0, CR: 0, LF: 0}
  for line in lines:
    if line.endswith(CRLF):
      endings[CRLF] += 1
    elif line.endswith(CR):
      endings[CR] += 1
    elif line.endswith(LF):
      endings[LF] += 1
  return (sorted(endings, key=endings.get, reverse=True) or [LF])[0]


def _FindPythonFiles(filenames, recursive, exclude):
  """Find all Python files."""
  if exclude and any(e.startswith('./') for e in exclude):
    raise errors.YapfError("path in '--exclude' should not start with ./")

  python_files = []
  for filename in filenames:
    if filename != '.' and exclude and IsIgnored(filename, exclude):
      continue
    if os.path.isdir(filename):
      if recursive:
        # TODO(morbo): Look into a version of os.walk that can handle recursion.
        excluded_dirs = []
        for dirpath, _, filelist in os.walk(filename):
          if dirpath != '.' and exclude and IsIgnored(dirpath, exclude):
            excluded_dirs.append(dirpath)
            continue
          elif any(dirpath.startswith(e) for e in excluded_dirs):
            continue
          for f in filelist:
            filepath = os.path.join(dirpath, f)
            if exclude and IsIgnored(filepath, exclude):
              continue
            if IsPythonFile(filepath):
              python_files.append(filepath)
      else:
        raise errors.YapfError(
            "directory specified without '--recursive' flag: %s" % filename)
    elif os.path.isfile(filename):
      python_files.append(filename)

  return python_files


def IsIgnored(path, exclude):
  """Return True if filename matches any patterns in exclude."""
  path = path.lstrip('/')
  while path.startswith('./'):
    path = path[2:]
  return any(fnmatch.fnmatch(path, e.rstrip('/')) for e in exclude)


def IsPythonFile(filename):
  """Return True if filename is a Python file."""
  if os.path.splitext(filename)[1] == '.py':
    return True

  try:
    with open(filename, 'rb') as fd:
      encoding = tokenize.detect_encoding(fd.readline)[0]

    # Check for correctness of encoding.
    with py3compat.open_with_encoding(
        filename, mode='r', encoding=encoding) as fd:
      fd.read()
  except UnicodeDecodeError:
    encoding = 'latin-1'
  except (IOError, SyntaxError):
    # If we fail to detect encoding (or the encoding cookie is incorrect - which
    # will make detect_encoding raise SyntaxError), assume it's not a Python
    # file.
    return False

  try:
    with py3compat.open_with_encoding(
        filename, mode='r', encoding=encoding) as fd:
      first_line = fd.readline(256)
  except IOError:
    return False

  return re.match(r'^#!.*\bpython[23]?\b', first_line)


def FileEncoding(filename):
  """Return the file's encoding."""
  with open(filename, 'rb') as fd:
    return tokenize.detect_encoding(fd.readline)[0]
