# -*- coding: utf-8 -*-
# Cardboardlint is a cheap lint solution for pull requests.
# Copyright (C) 2011-2017 The Cardboardlint Development Team
#
# This file is part of Cardboardlint.
#
# Cardboardlint is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# Cardboardlint is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <http://www.gnu.org/licenses/>
# --
"""Linter for whitespace conventions.

This script checks for three ugly things: tabs, trailing whitespace and trailing newlines.
"""
from __future__ import print_function

import codecs
from typing import List

from cardboardlint.common import Message, Linter


__all__ = ['linter_whitespace']


DEFAULT_CONFIG = {
    # Filename filter rules
    'filefilter': ['+ *.*'],
}


def run_whitespace(_config, filenames):
    """Linter for checking whitespace conventions.

    Parameters
    ----------
    config : dict
        Dictionary that contains the configuration for the linter
    filenames : list
        A list of filenames to check

    Returns
    -------
    messages : list
        The list of messages generated by the external linter.

    """
    # Loop over all files and check whitespace in each file.
    messages = []
    for filename in filenames:
        try:
            _check_file(filename, messages)
        except UnicodeDecodeError as err:
            messages.append(Message(filename, None, None, str(err)))
    return messages


def _check_file(filename: str, messages: List[str]):
    """Look for white-space issues.

    Parameters
    ----------
    filename
        File to be checked
    messages
        A list of messages to append to. (output arg)

    """
    with codecs.open(filename, encoding='utf-8') as f:
        line = None
        lineno = -1
        for lineno, line in enumerate(f):
            # Check for tabs
            charno = line.find('\t')
            if charno >= 0:
                messages.append(Message(filename, lineno + 1, charno + 1, 'tab'))
            # Check for carriage return
            charno = line.find('\r')
            if charno >= 0:
                messages.append(Message(filename, lineno + 1, charno + 1, 'carriage return'))
            # Check for trailing whitespace
            if line[:-1] != line.rstrip():
                messages.append(Message(filename, lineno + 1, None, 'trailing whitespace'))
        # Perform some checks on the last line
        if line is not None:
            if len(line.strip()) == 0:
                messages.append(Message(filename, lineno + 1, None, 'trailing empty line'))
            if not line.endswith("\n"):
                messages.append(Message(filename, lineno + 1, None, 'last line missing \\n'))


# pylint: disable=invalid-name
linter_whitespace = Linter('whitespace', run_whitespace, DEFAULT_CONFIG)
