"""The Base module of the :mod:`python_linter` package. This holds the objects shared by
multiple modules."""
import io
import os
import logging

FOUND_RICH_LIB = False
try:
    from rich.logging import RichHandler

    FOUND_RICH_LIB = True

    logging.basicConfig(
        format="%(name)s: %(message)s",
        handlers=[RichHandler(show_time=False)],
    )

except ImportError:
    logging.basicConfig()

#: The logging.Logger object used for outputting data.
logger = logging.getLogger("Python Checker")
if not FOUND_RICH_LIB:
    logger.debug("rich module not found")

# setup a separate logger for using github log commands
log_commander = logger.getChild("LOG COMMANDER")  # create a child of our logger obj
log_commander.setLevel(logging.DEBUG)  # be sure that log commands are output
console_handler = logging.StreamHandler()  # Create special stdout stream handler
console_handler.setFormatter(logging.Formatter("%(message)s"))  # no formatted log cmds
log_commander.addHandler(console_handler)  # Use special handler for log_commander
log_commander.propagate = False  # prevent duplicate messages in the parent logger obj


class Globals:
    """Global variables for re-use (non-constant)."""

    #: The responding payload containing info about changed files.
    FILES = []
    #: The parsed JSON of the event payload.
    EVENT_PAYLOAD = {}
    #: A shared response object for `requests` module.
    response_buffer = None


class GlobalParser:
    """Global variables specific to output parsers. Each element in each of the
    following attributes represents a clang-tool's output for 1 source file.
    """

    #: This can only be a `list` of JSON-type `dict` (generated by pylint)
    pylint_notes = []
    #: This can only be a `list` of type ??? (not implemented yet)
    black_advice = []


def start_log_group(name: str) -> None:
    """Begin a collapsable group of log statements.

    Args:
        name: The name of the collapsable group
    """
    log_commander.fatal("::group::%s", name)


def end_log_group() -> None:
    """End a collapsable group of log statements."""
    log_commander.fatal("::endgroup::")


def get_lines_from_file(file_path: str) -> list:
    """Get all the lines from a file as a list of strings.

    :param str file_path: The path to the file.
    :Returns: A list of lines (each a `str`).
    """
    with open(file_path, encoding="utf-8") as temp:
        return temp.readlines()


def get_line_cnt_from_cols(file_path: str, offset: int) -> tuple:
    """Gets a line count and columns offset from a file's absolute offset.

    :param str file_path: Path to file.
    :param int offset: The byte offset to translate

    Returns:
        A `tuple` of 2 `int` numbers:

        - Index 0 is the line number for the given offset.
        - Index 1 is the column number for the given offset on the line.
    """
    line_cnt = 1
    last_lf_pos = 0
    cols = 1
    file_path = file_path.replace("/", os.sep)
    with io.open(file_path, "r", encoding="utf-8", newline="\n") as src_file:
        src_file.seek(0, io.SEEK_END)
        max_len = src_file.tell()
        src_file.seek(0, io.SEEK_SET)
        while src_file.tell() != offset and src_file.tell() < max_len:
            char = src_file.read(1)
            if char == "\n":
                line_cnt += 1
                last_lf_pos = src_file.tell() - 1  # -1 because LF is part of offset
                if last_lf_pos + 1 > max_len:
                    src_file.newlines = "\r\n"
                    src_file.seek(0, io.SEEK_SET)
                    line_cnt = 1
        cols = src_file.tell() - last_lf_pos
    return (line_cnt, cols)

"""The Base module of the :mod:`python_linter` package. This holds the objects shared by
multiple modules."""
import io
import os
import logging

FOUND_RICH_LIB = False
try:
    from rich.logging import RichHandler

    FOUND_RICH_LIB = True

    logging.basicConfig(
        format="%(name)s: %(message)s",
        handlers=[RichHandler(show_time=False)],
    )

except ImportError:
    logging.basicConfig()

#: The logging.Logger object used for outputting data.
logger = logging.getLogger("Python Checker")
if not FOUND_RICH_LIB:
    logger.debug("rich module not found")

# setup a separate logger for using github log commands
log_commander = logger.getChild("LOG COMMANDER")  # create a child of our logger obj
log_commander.setLevel(logging.DEBUG)  # be sure that log commands are output
console_handler = logging.StreamHandler()  # Create special stdout stream handler
console_handler.setFormatter(logging.Formatter("%(message)s"))  # no formatted log cmds
log_commander.addHandler(console_handler)  # Use special handler for log_commander
log_commander.propagate = False  # prevent duplicate messages in the parent logger obj


class Globals:
    """Global variables for re-use (non-constant)."""

    #: The responding payload containing info about changed files.
    FILES = []
    #: The parsed JSON of the event payload.
    EVENT_PAYLOAD = {}
    #: A shared response object for `requests` module.
    response_buffer = None


class GlobalParser:
    """Global variables specific to output parsers. Each element in each of the
    following attributes represents a clang-tool's output for 1 source file.
    """

    #: This can only be a `list` of JSON-type `dict` (generated by pylint)
    pylint_notes = []
    #: This can only be a `list` of type ??? (not implemented yet)
    black_advice = []


def start_log_group(name: str) -> None:
    """Begin a collapsable group of log statements.

    Args:
        name: The name of the collapsable group
    """
    log_commander.fatal("::group::%s", name)


def end_log_group() -> None:
    """End a collapsable group of log statements."""
    log_commander.fatal("::endgroup::")


def get_lines_from_file(file_path: str) -> list:
    """Get all the lines from a file as a list of strings.

    :param str file_path: The path to the file.
    :Returns: A list of lines (each a `str`).
    """
    with open(file_path, encoding="utf-8") as temp:
        return temp.readlines()


def get_line_cnt_from_cols(file_path: str, offset: int) -> tuple:
    """Gets a line count and columns offset from a file's absolute offset.

    :param str file_path: Path to file.
    :param int offset: The byte offset to translate

    Returns:
        A `tuple` of 2 `int` numbers:

        - Index 0 is the line number for the given offset.
        - Index 1 is the column number for the given offset on the line.
    """
    line_cnt = 1
    last_lf_pos = 0
    cols = 1
    file_path = file_path.replace("/", os.sep)
    with io.open(file_path, "r", encoding="utf-8", newline="\n") as src_file:
        src_file.seek(0, io.SEEK_END)
        max_len = src_file.tell()
        src_file.seek(0, io.SEEK_SET)
        while src_file.tell() != offset and src_file.tell() < max_len:
            char = src_file.read(1)
            if char == "\n":
                line_cnt += 1
                last_lf_pos = src_file.tell() - 1  # -1 because LF is part of offset
                if last_lf_pos + 1 > max_len:
                    src_file.newlines = "\r\n"
                    src_file.seek(0, io.SEEK_SET)
                    line_cnt = 1
        cols = src_file.tell() - last_lf_pos
    return (line_cnt, cols)

The Base module of the :mod:`python_linter` package. This holds the objects shared by multiple modules. #: The logging.Logger object used for outputting data. # setup a separate logger for using github log commands # create a child of our logger obj # be sure that log commands are output # Create special stdout stream handler # no formatted log cmds # Use special handler for log_commander # prevent duplicate messages in the parent logger obj Global variables for re-use (non-constant). #: The responding payload containing info about changed files. #: The parsed JSON of the event payload. #: A shared response object for `requests` module. Global variables specific to output parsers. Each element in each of the     following attributes represents a clang-tool's output for 1 source file. #: This can only be a `list` of JSON-type `dict` (generated by pylint) #: This can only be a `list` of type ??? (not implemented yet) Begin a collapsable group of log statements.      Args:         name: The name of the collapsable group End a collapsable group of log statements. Get all the lines from a file as a list of strings.      :param str file_path: The path to the file.     :Returns: A list of lines (each a `str`). Gets a line count and columns offset from a file's absolute offset.      :param str file_path: Path to file.     :param int offset: The byte offset to translate      Returns:         A `tuple` of 2 `int` numbers:          - Index 0 is the line number for the given offset.         - Index 1 is the column number for the given offset on the line. # -1 because LF is part of offset