# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
r"""
Class describing lint configuration object
"""

import hjson
import logging as log
from pathlib import Path

from tabulate import tabulate

from OneShotCfg import OneShotCfg
from utils import VERBOSE, print_msg_list, subst_wildcards


class LintCfg(OneShotCfg):
    """Derivative class for linting purposes.
    """

    flow = 'lint'

    def __init__(self, flow_cfg_file, hjson_data, args, mk_config):
        # This is a lint-specific attribute
        self.is_style_lint = ""
        super().__init__(flow_cfg_file, hjson_data, args, mk_config)

        # Convert to boolean
        if self.is_style_lint == "True":
            self.is_style_lint = True
        else:
            self.is_style_lint = False

        # Set the title for lint results.
        if self.is_style_lint:
            self.results_title = self.name.upper() + " Style Lint Results"
        else:
            self.results_title = self.name.upper() + " Lint Results"

    def gen_results_summary(self):
        '''
        Gathers the aggregated results from all sub configs
        '''

        # Generate results table for runs.
        log.info("Create summary of lint results")

        results_str = "## " + self.results_title + " (Summary)\n\n"
        results_str += "### " + self.timestamp_long + "\n"
        if self.revision:
            results_str += "### " + self.revision + "\n"
        results_str += "### Branch: " + self.branch + "\n"
        results_str += "\n"

        header = [
            "Name", "Tool Warnings", "Tool Errors", "Lint Warnings",
            "Lint Errors"
        ]
        colalign = ("center", ) * len(header)
        table = [header]

        for cfg in self.cfgs:

            results_page = cfg.results_server_dir + '/results.html'
            results_page_url = results_page.replace(
                cfg.results_server_prefix, cfg.results_server_url_prefix)
            name_with_link = "[" + cfg.name.upper(
            ) + "](" + results_page_url + ")"
            table.append([
                name_with_link,
                str(len(cfg.result_summary["warnings"])) + " W",
                str(len(cfg.result_summary["errors"])) + " E",
                str(len(cfg.result_summary["lint_warnings"])) + " W",
                str(len(cfg.result_summary["lint_errors"])) + " E"
            ])

        if len(table) > 1:
            self.results_summary_md = results_str + tabulate(
                table, headers="firstrow", tablefmt="pipe",
                colalign=colalign) + "\n"
        else:
            self.results_summary_md = results_str + "\nNo results to display.\n"

        print(self.results_summary_md)

        # Return only the tables
        return self.results_summary_md

    def _gen_results(self, results):
        # '''
        # The function is called after the regression has completed. It looks
        # for a regr_results.hjson file with aggregated results from the lint run.
        # The hjson needs to have the following (potentially empty) fields
        #
        # {
        #   tool: ""
        #   errors: []
        #   warnings: []
        #   lint_errors: []
        #   lint_warning: []
        #   lint_infos: []
        # }
        #
        # where each entry is a string representing a lint message. This allows
        # to reuse the same LintCfg class with different tools since just the
        # parsing script that transforms the tool output into the hjson above
        # needs to be adapted.
        #
        # note that if this is a primary config, the results will
        # be generated using the _gen_results_summary function
        # '''

        # Generate results table for runs.
        results_str = "## " + self.results_title + "\n\n"
        results_str += "### " + self.timestamp_long + "\n"
        if self.revision:
            results_str += "### " + self.revision + "\n"
        results_str += "### Branch: " + self.branch + "\n"
        results_str += "### Lint Tool: " + self.tool.upper() + "\n\n"

        header = [
            "Build Mode", "Tool Warnings", "Tool Errors", "Lint Warnings",
            "Lint Errors"
        ]
        colalign = ("center", ) * len(header)
        table = [header]

        # aggregated counts
        self.result_summary["warnings"] = []
        self.result_summary["errors"] = []
        self.result_summary["lint_warnings"] = []
        self.result_summary["lint_errors"] = []

        fail_msgs = ""
        for mode in self.build_modes:

            result_data = Path(
                subst_wildcards(self.build_dir, {"build_mode": mode.name}) +
                '/results.hjson')
            log.info("[results:hjson]: [%s]: [%s]", self.name, result_data)

            try:
                with result_data.open() as results_file:
                    self.result = hjson.load(results_file, use_decimal=True)
            except IOError as err:
                log.warning("%s", err)
                self.result = {
                    "tool": "",
                    "errors": ["IOError: %s" % err],
                    "warnings": [],
                    "lint_errors": [],
                    "lint_warnings": [],
                    "lint_infos": []
                }
            if self.result:
                table.append([
                    mode.name,
                    str(len(self.result["warnings"])) + " W ",
                    str(len(self.result["errors"])) + " E",
                    # We currently do not publish these infos at
                    # the moment len(self.result["lint_infos"]),
                    str(len(self.result["lint_warnings"])) + " W",
                    str(len(self.result["lint_errors"])) + " E"
                ])
            else:
                self.result = {
                    "tool": "",
                    "errors": [],
                    "warnings": [],
                    "lint_errors": [],
                    "lint_warnings": [],
                    "lint_infos": []
                }

            self.result_summary["warnings"] += self.result["warnings"]
            self.result_summary["errors"] += self.result["errors"]
            self.result_summary["lint_warnings"] += self.result[
                "lint_warnings"]
            self.result_summary["lint_errors"] += self.result["lint_errors"]

            # Append detailed messages if they exist
            hdr_key_pairs = [("Tool Warnings", "warnings"),
                             ("Tool Errors", "errors"),
                             ("Lint Warnings", "lint_warnings"),
                             ("Lint Errors", "lint_errors")]

            # Lint fails if any warning or error message has occurred
            self.errors_seen = False
            for _, key in hdr_key_pairs:
                if key in self.result:
                    if self.result.get(key):
                        self.errors_seen = True
                        break

            if self.errors_seen:
                fail_msgs += "\n### Errors and Warnings for Build Mode `'" + mode.name + "'`\n"
                for hdr, key in hdr_key_pairs:
                    msgs = self.result.get(key)
                    fail_msgs += print_msg_list("#### " + hdr, msgs, self.max_msg_count)

        if len(table) > 1:
            self.results_md = results_str + tabulate(
                table, headers="firstrow", tablefmt="pipe",
                colalign=colalign) + "\n"

            # the email and published reports will default to self.results_md if they are
            # empty. in case they need to be sanitized, override them and do not append
            # detailed messages.
            if self.sanitize_email_results:
                self.email_results_md = self.results_md
            if self.sanitize_publish_results:
                self.publish_results_md = self.results_md
            # locally generated result always contains all details
            self.results_md += fail_msgs
        else:
            self.results_md = results_str + "\nNo results to display.\n"
            self.email_results_md = self.results_md
            self.publish_results_md = self.results_md

        return self.results_md
