"""ntc_templates.parse."""

import os

# Due to TextFSM library issues on Windows, it is better to not fail on import
# Instead fail at runtime (i.e. if method is actually used).
try:
    from textfsm import clitable

    HAS_CLITABLE = True
except ImportError:
    HAS_CLITABLE = False


class ParsingException(Exception):
    """Error that is raised when TextFSM hits an `Error` state."""


def _get_template_dir():
    template_dir = os.environ.get("NTC_TEMPLATES_DIR")
    if template_dir is None:
        package_dir = os.path.dirname(__file__)
        template_dir = os.path.join(package_dir, "templates")
        if not os.path.isdir(template_dir):
            project_dir = os.path.dirname(os.path.dirname(os.path.dirname(template_dir)))
            template_dir = os.path.join(project_dir, "templates")

    return template_dir


def _clitable_to_dict(cli_table):
    """Convert TextFSM cli_table object to list of dictionaries."""
    objs = []
    for row in cli_table:
        temp_dict = {}
        for index, element in enumerate(row):
            temp_dict[cli_table.header[index].lower()] = element
        objs.append(temp_dict)

    return objs


def parse_output(
    platform=None,
    command=None,
    data=None,
    template_dir=None,
    try_fallback=False,
):
    """Return the structured data based on the output from a network device.

    Args:
        platform: The platform the command was run on (e.g., `cisco_ios`).
        command: The command run on the platform (e.g., `show int status`).
        data: The output from running the command.
        template_dir: The directory to look for TextFSM templates.
            Defaults to setting of environment variable or default ntc-templates dir.
            The specified directory must have a properly configured index file.
        try_fallback: Whether to fallback to using the default template directory upon failure with `template_dir`.

    Returns:
        list: The TextFSM table entries as dictionaries.
    """
    if not HAS_CLITABLE:
        msg = (
            "The TextFSM library is not currently supported on Windows. If you are NOT using Windows "
            "you should be able to 'pip install textfsm' to fix this issue. If you are using Windows "
            "then you will need to install the patch referenced here:\n\n"
            "https://github.com/google/textfsm/pull/82\n\n"
        )
        raise ImportError(msg)

    template_dir = template_dir or _get_template_dir()
    cli_table = clitable.CliTable("index", template_dir)
    attrs = {"Command": command, "Platform": platform}
    try:
        cli_table.ParseCmd(data, attrs)
        structured_data = _clitable_to_dict(cli_table)
    except clitable.CliTableError as err:
        if try_fallback and template_dir != _get_template_dir():
            return parse_output(platform, command, data)
        raise ParsingException(f'Unable to parse command "{command}" on platform {platform} - {str(err)}') from err

    return structured_data
