# -*- coding: utf-8 -*-

# Copyright (c) 2014 - 2021 Detlev Offenbach <detlev@die-offenbachs.de>
#

"""
Module implementing message translations for the code style plugin messages.
"""

from PyQt5.QtCore import QCoreApplication

from .Security.translations import (
    _securityMessages, _securityMessagesSampleArgs
)
from .Annotations.translations import (
    _annotationsMessages, _annotationsMessagesSampleArgs
)
from .Complexity.translations import (
    _complexityMessages, _complexityMessagesSampleArgs
)
from .DocStyle.translations import (
    _docStyleMessages, _docStyleMessagesSampleArgs
)
from .Miscellaneous.translations import (
    _miscellaneousMessages, _miscellaneousMessagesSampleArgs
)
from .Naming.translations import _namingStyleMessages

_messages = {
    ##################################################################
    ## pycodestyle messages
    ##################################################################
    "E101": QCoreApplication.translate(
        "pycodestyle",
        "indentation contains mixed spaces and tabs"),
    "E111": QCoreApplication.translate(
        "pycodestyle",
        "indentation is not a multiple of four"),
    "E112": QCoreApplication.translate(
        "pycodestyle",
        "expected an indented block"),
    "E113": QCoreApplication.translate(
        "pycodestyle",
        "unexpected indentation"),
    "E114": QCoreApplication.translate(
        "pycodestyle",
        "indentation is not a multiple of four (comment)"),
    "E115": QCoreApplication.translate(
        "pycodestyle",
        "expected an indented block (comment)"),
    "E116": QCoreApplication.translate(
        "pycodestyle",
        "unexpected indentation (comment)"),
    "E117": QCoreApplication.translate(
        "pycodestyle",
        "over-indented"),
    "E121": QCoreApplication.translate(
        "pycodestyle",
        "continuation line indentation is not a multiple of four"),
    "E122": QCoreApplication.translate(
        "pycodestyle",
        "continuation line missing indentation or outdented"),
    "E123": QCoreApplication.translate(
        "pycodestyle",
        "closing bracket does not match indentation of opening"
        " bracket's line"),
    "E124": QCoreApplication.translate(
        "pycodestyle",
        "closing bracket does not match visual indentation"),
    "E125": QCoreApplication.translate(
        "pycodestyle",
        "continuation line with same indent as next logical line"),
    "E126": QCoreApplication.translate(
        "pycodestyle",
        "continuation line over-indented for hanging indent"),
    "E127": QCoreApplication.translate(
        "pycodestyle",
        "continuation line over-indented for visual indent"),
    "E128": QCoreApplication.translate(
        "pycodestyle",
        "continuation line under-indented for visual indent"),
    "E129": QCoreApplication.translate(
        "pycodestyle",
        "visually indented line with same indent as next logical line"),
    "E131": QCoreApplication.translate(
        "pycodestyle",
        "continuation line unaligned for hanging indent"),
    "E133": QCoreApplication.translate(
        "pycodestyle",
        "closing bracket is missing indentation"),
    "W191": QCoreApplication.translate(
        "pycodestyle",
        "indentation contains tabs"),
    "E201": QCoreApplication.translate(
        "pycodestyle",
        "whitespace after '{0}'"),
    "E202": QCoreApplication.translate(
        "pycodestyle",
        "whitespace before '{0}'"),
    "E203": QCoreApplication.translate(
        "pycodestyle",
        "whitespace before '{0}'"),
    "E211": QCoreApplication.translate(
        "pycodestyle",
        "whitespace before '{0}'"),
    "E221": QCoreApplication.translate(
        "pycodestyle",
        "multiple spaces before operator"),
    "E222": QCoreApplication.translate(
        "pycodestyle",
        "multiple spaces after operator"),
    "E223": QCoreApplication.translate(
        "pycodestyle",
        "tab before operator"),
    "E224": QCoreApplication.translate(
        "pycodestyle",
        "tab after operator"),
    "E225": QCoreApplication.translate(
        "pycodestyle",
        "missing whitespace around operator"),
    "E226": QCoreApplication.translate(
        "pycodestyle",
        "missing whitespace around arithmetic operator"),
    "E227": QCoreApplication.translate(
        "pycodestyle",
        "missing whitespace around bitwise or shift operator"),
    "E228": QCoreApplication.translate(
        "pycodestyle",
        "missing whitespace around modulo operator"),
    "E231": QCoreApplication.translate(
        "pycodestyle",
        "missing whitespace after '{0}'"),
    "E241": QCoreApplication.translate(
        "pycodestyle",
        "multiple spaces after '{0}'"),
    "E242": QCoreApplication.translate(
        "pycodestyle",
        "tab after '{0}'"),
    "E251": QCoreApplication.translate(
        "pycodestyle",
        "unexpected spaces around keyword / parameter equals"),
    "E252": QCoreApplication.translate(
        "pycodestyle",
        "missing whitespace around parameter equals"),
    "E261": QCoreApplication.translate(
        "pycodestyle",
        "at least two spaces before inline comment"),
    "E262": QCoreApplication.translate(
        "pycodestyle",
        "inline comment should start with '# '"),
    "E265": QCoreApplication.translate(
        "pycodestyle",
        "block comment should start with '# '"),
    "E266": QCoreApplication.translate(
        "pycodestyle",
        "too many leading '#' for block comment"),
    "E271": QCoreApplication.translate(
        "pycodestyle",
        "multiple spaces after keyword"),
    "E272": QCoreApplication.translate(
        "pycodestyle",
        "multiple spaces before keyword"),
    "E273": QCoreApplication.translate(
        "pycodestyle",
        "tab after keyword"),
    "E274": QCoreApplication.translate(
        "pycodestyle",
        "tab before keyword"),
    "E275": QCoreApplication.translate(
        "pycodestyle",
        "missing whitespace after keyword"),
    "W291": QCoreApplication.translate(
        "pycodestyle",
        "trailing whitespace"),
    "W292": QCoreApplication.translate(
        "pycodestyle",
        "no newline at end of file"),
    "W293": QCoreApplication.translate(
        "pycodestyle",
        "blank line contains whitespace"),
    "E301": QCoreApplication.translate(
        "pycodestyle",
        "expected {0} blank lines, found {1}"),
    "E302": QCoreApplication.translate(
        "pycodestyle",
        "expected {0} blank lines, found {1}"),
    "E303": QCoreApplication.translate(
        "pycodestyle",
        "too many blank lines ({0}), expected {1}"),
    "E304": QCoreApplication.translate(
        "pycodestyle",
        "blank lines found after function decorator"),
    "E305": QCoreApplication.translate(
        "pycodestyle",
        "expected {0} blank lines after class or function definition,"
        " found {1}"),
    "E306": QCoreApplication.translate(
        "pycodestyle",
        "expected {0} blank lines before a nested definition, found {1}"),
    "E307": QCoreApplication.translate(
        "pycodestyle",
        "too many blank lines ({0}) before a nested definition, expected {1}"),
    "E308": QCoreApplication.translate(
        "pycodestyle",
        "too many blank lines ({0})"),
    "W391": QCoreApplication.translate(
        "pycodestyle",
        "blank line at end of file"),
    "E401": QCoreApplication.translate(
        "pycodestyle",
        "multiple imports on one line"),
    "E402": QCoreApplication.translate(
        "pycodestyle",
        "module level import not at top of file"),
    "E501": QCoreApplication.translate(
        "pycodestyle",
        "line too long ({0} > {1} characters)"),
    "E502": QCoreApplication.translate(
        "pycodestyle",
        "the backslash is redundant between brackets"),
    "W503": QCoreApplication.translate(
        "pycodestyle",
        "line break before binary operator"),
    "W504": QCoreApplication.translate(
        "pycodestyle",
        "line break after binary operator"),
    "W505": QCoreApplication.translate(
        "pycodestyle",
        "doc line too long ({0} > {1} characters)"),
    "W601": QCoreApplication.translate(
        "pycodestyle",
        ".has_key() is deprecated, use 'in'"),
    "W602": QCoreApplication.translate(
        "pycodestyle",
        "deprecated form of raising exception"),
    "W603": QCoreApplication.translate(
        "pycodestyle",
        "'<>' is deprecated, use '!='"),
    "W604": QCoreApplication.translate(
        "pycodestyle",
        "backticks are deprecated, use 'repr()'"),
    "W605": QCoreApplication.translate(
        "pycodestyle",
        "invalid escape sequence '\\{0}'"),
    "W606": QCoreApplication.translate(
        "pycodestyle",
        "'async' and 'await' are reserved keywords starting with Python 3.7"),
    "E701": QCoreApplication.translate(
        "pycodestyle",
        "multiple statements on one line (colon)"),
    "E702": QCoreApplication.translate(
        "pycodestyle",
        "multiple statements on one line (semicolon)"),
    "E703": QCoreApplication.translate(
        "pycodestyle",
        "statement ends with a semicolon"),
    "E704": QCoreApplication.translate(
        "pycodestyle",
        "multiple statements on one line (def)"),
    "E711": QCoreApplication.translate(
        "pycodestyle",
        "comparison to {0} should be {1}"),
    "E712": QCoreApplication.translate(
        "pycodestyle",
        "comparison to {0} should be {1}"),
    "E713": QCoreApplication.translate(
        "pycodestyle",
        "test for membership should be 'not in'"),
    "E714": QCoreApplication.translate(
        "pycodestyle",
        "test for object identity should be 'is not'"),
    "E721": QCoreApplication.translate(
        "pycodestyle",
        "do not compare types, use 'isinstance()'"),
    "E722": QCoreApplication.translate(
        "pycodestyle",
        "do not use bare except"),
    "E731": QCoreApplication.translate(
        "pycodestyle",
        "do not assign a lambda expression, use a def"),
    "E741": QCoreApplication.translate(
        "pycodestyle",
        "ambiguous variable name '{0}'"),
    "E742": QCoreApplication.translate(
        "pycodestyle",
        "ambiguous class definition '{0}'"),
    "E743": QCoreApplication.translate(
        "pycodestyle",
        "ambiguous function definition '{0}'"),
    "E901": QCoreApplication.translate(
        "pycodestyle",
        "{0}: {1}"),
    "E902": QCoreApplication.translate(
        "pycodestyle",
        "{0}"),
    
    ##################################################################
    ## CodeStyleFixer messages
    ##################################################################
    
    "FIXD111": QCoreApplication.translate(
        'CodeStyleFixer',
        "Triple single quotes converted to triple double quotes."),
    'FIXD112': QCoreApplication.translate(
        'CodeStyleFixer',
        'Introductory quotes corrected to be {0}"""'),
    "FIXD121": QCoreApplication.translate(
        'CodeStyleFixer',
        "Single line docstring put on one line."),
    "FIXD131": QCoreApplication.translate(
        'CodeStyleFixer',
        "Period added to summary line."),
    "FIXD141": QCoreApplication.translate(
        'CodeStyleFixer',
        "Blank line before function/method docstring removed."),
    "FIXD142": QCoreApplication.translate(
        'CodeStyleFixer',
        "Blank line inserted before class docstring."),
    "FIXD143": QCoreApplication.translate(
        'CodeStyleFixer',
        "Blank line inserted after class docstring."),
    "FIXD144": QCoreApplication.translate(
        'CodeStyleFixer',
        "Blank line inserted after docstring summary."),
    "FIXD145": QCoreApplication.translate(
        'CodeStyleFixer',
        "Blank line inserted after last paragraph of docstring."),
    "FIXD221": QCoreApplication.translate(
        'CodeStyleFixer',
        "Leading quotes put on separate line."),
    "FIXD222": QCoreApplication.translate(
        'CodeStyleFixer',
        "Trailing quotes put on separate line."),
    "FIXD242": QCoreApplication.translate(
        'CodeStyleFixer',
        "Blank line before class docstring removed."),
    "FIXD244": QCoreApplication.translate(
        'CodeStyleFixer',
        "Blank line before function/method docstring removed."),
    "FIXD243": QCoreApplication.translate(
        'CodeStyleFixer',
        "Blank line after class docstring removed."),
    "FIXD245": QCoreApplication.translate(
        'CodeStyleFixer',
        "Blank line after function/method docstring removed."),
    "FIXD247": QCoreApplication.translate(
        'CodeStyleFixer',
        "Blank line after last paragraph removed."),
    "FIXE101": QCoreApplication.translate(
        'CodeStyleFixer',
        "Tab converted to 4 spaces."),
    "FIXE111": QCoreApplication.translate(
        'CodeStyleFixer',
        "Indentation adjusted to be a multiple of four."),
    "FIXE121": QCoreApplication.translate(
        'CodeStyleFixer',
        "Indentation of continuation line corrected."),
    "FIXE124": QCoreApplication.translate(
        'CodeStyleFixer',
        "Indentation of closing bracket corrected."),
    "FIXE122": QCoreApplication.translate(
        'CodeStyleFixer',
        "Missing indentation of continuation line corrected."),
    "FIXE123": QCoreApplication.translate(
        'CodeStyleFixer',
        "Closing bracket aligned to opening bracket."),
    "FIXE125": QCoreApplication.translate(
        'CodeStyleFixer',
        "Indentation level changed."),
    "FIXE126": QCoreApplication.translate(
        'CodeStyleFixer',
        "Indentation level of hanging indentation changed."),
    "FIXE127": QCoreApplication.translate(
        'CodeStyleFixer',
        "Visual indentation corrected."),
    "FIXE201": QCoreApplication.translate(
        'CodeStyleFixer',
        "Extraneous whitespace removed."),
    "FIXE225": QCoreApplication.translate(
        'CodeStyleFixer',
        "Missing whitespace added."),
    "FIXE221": QCoreApplication.translate(
        'CodeStyleFixer',
        "Extraneous whitespace removed."),
    "FIXE231": QCoreApplication.translate(
        'CodeStyleFixer',
        "Missing whitespace added."),
    "FIXE251": QCoreApplication.translate(
        'CodeStyleFixer',
        "Extraneous whitespace removed."),
    "FIXE261": QCoreApplication.translate(
        'CodeStyleFixer',
        "Whitespace around comment sign corrected."),
    
    "FIXE302+": lambda n=1: QCoreApplication.translate(
        'CodeStyleFixer',
        "%n blank line(s) inserted.", '', n),
    "FIXE302-": lambda n=1: QCoreApplication.translate(
        'CodeStyleFixer',
        "%n superfluous lines removed", '', n),
    
    "FIXE303": QCoreApplication.translate(
        'CodeStyleFixer',
        "Superfluous blank lines removed."),
    "FIXE304": QCoreApplication.translate(
        'CodeStyleFixer',
        "Superfluous blank lines after function decorator removed."),
    "FIXE401": QCoreApplication.translate(
        'CodeStyleFixer',
        "Imports were put on separate lines."),
    "FIXE501": QCoreApplication.translate(
        'CodeStyleFixer',
        "Long lines have been shortened."),
    "FIXE502": QCoreApplication.translate(
        'CodeStyleFixer',
        "Redundant backslash in brackets removed."),
    "FIXE701": QCoreApplication.translate(
        'CodeStyleFixer',
        "Compound statement corrected."),
    "FIXE702": QCoreApplication.translate(
        'CodeStyleFixer',
        "Compound statement corrected."),
    "FIXE711": QCoreApplication.translate(
        'CodeStyleFixer',
        "Comparison to None/True/False corrected."),
    "FIXN804": QCoreApplication.translate(
        'CodeStyleFixer',
        "'{0}' argument added."),
    "FIXN806": QCoreApplication.translate(
        'CodeStyleFixer',
        "'{0}' argument removed."),
    "FIXW291": QCoreApplication.translate(
        'CodeStyleFixer',
        "Whitespace stripped from end of line."),
    "FIXW292": QCoreApplication.translate(
        'CodeStyleFixer',
        "newline added to end of file."),
    "FIXW391": QCoreApplication.translate(
        'CodeStyleFixer',
        "Superfluous trailing blank lines removed from end of file."),
    "FIXW603": QCoreApplication.translate(
        'CodeStyleFixer',
        "'<>' replaced by '!='."),
        
    "FIXWRITE_ERROR": QCoreApplication.translate(
        'CodeStyleFixer',
        "Could not save the file! Skipping it. Reason: {0}"),
}

_messages_sample_args = {
    "E201": ["([{"],
    "E202": ["}])"],
    "E203": [",;:"],
    "E211": ["(["],
    "E231": [",;:"],
    "E241": [",;:"],
    "E242": [",;:"],
    "E301": [1, 0],
    "E302": [2, 1],
    "E303": [3, 2],
    "E305": [2, 1],
    "E306": [1, 0],
    "E307": [3, 1],
    "E308": [3],
    "E501": [85, 79],
    "W505": [80, 72],
    "E605": ["A"],
    "E711": ["None", "'if cond is None:'"],
    "E712": ["True", "'if cond is True:' or 'if cond:'"],
    "E741": ["l"],
    "E742": ["l"],
    "E743": ["l"],
    "E901": ["SyntaxError", "Invalid Syntax"],
    "E902": ["OSError"],
    
    "FIXWRITE_ERROR": ["OSError"],
}

messageCatalogs = (
    _messages,
    _securityMessages,
    _annotationsMessages,
    _complexityMessages,
    _docStyleMessages,
    _miscellaneousMessages,
    _namingStyleMessages,
)

messageSampleArgsCatalog = (
    _messages_sample_args,
    _securityMessagesSampleArgs,
    _annotationsMessagesSampleArgs,
    _complexityMessagesSampleArgs,
    _docStyleMessagesSampleArgs,
    _miscellaneousMessagesSampleArgs,
)


def getTranslatedMessage(messageCode, messageArgs, example=False):
    """
    Module function to get a translated and formatted message for a
    given message ID.
    
    @param messageCode the message code
    @type str
    @param messageArgs list of arguments or a single integer value to format
        the message
    @type list or int
    @param example flag indicating a translated message filled with example
        data is requested (messageArgs is ignored if given)
    @type bool
    @return translated and formatted message
    @rtype str
    """
    if example:
        for argsCatalog in messageSampleArgsCatalog:
            if messageCode in argsCatalog:
                args = argsCatalog[messageCode]
                break
        else:
            args = None
    else:
        args = messageArgs
    
    for catalog in messageCatalogs:
        if messageCode in catalog:
            if args is None:
                return catalog[messageCode]
            elif isinstance(args, int):
                # Retranslate with correct plural form
                return catalog[messageCode](args)
            else:
                return catalog[messageCode].format(*args)
    else:
        if example:
            return None
        else:
            return QCoreApplication.translate(
                "CodeStyleChecker",
                "No message defined for code '{0}'."
            ).format(messageCode)


def getMessageCodes():
    """
    Module function to get a list of known message codes.
    
    @return list of known message codes
    @rtype set of str
    """
    knownCodes = []
    for catalog in messageCatalogs:
        knownCodes += list(catalog.keys())
    return {c.split(".", 1)[0] for c in knownCodes}

#
# eflag: noqa = M201
