# 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 print_msg_list, subst_wildcards


class LintCfg(OneShotCfg):
    """Derivative class for linting purposes.
    """
    def __init__(self, flow_cfg_file, proj_root, args):
        # This is a lint-specific attribute
        self.is_style_lint = ""
        super().__init__(flow_cfg_file, proj_root, args)

    def __post_init__(self):
        super().__post_init__()

        # 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_string:
            results_str += "### " + self.revision_string + "\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):
        # '''
        # 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 master 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_string:
            results_str += "### " + self.revision_string + "\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("looking for result data file at %s", result_data)

            try:
                with open(result_data, "r") 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")]

            has_msg = False
            for _, key in hdr_key_pairs:
                if key in self.result:
                    has_msg = True
                    break

            if has_msg:
                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

        # Write results to the scratch area
        self.results_file = self.scratch_path + "/results_" + self.timestamp + ".md"
        with open(self.results_file, 'w') as f:
            f.write(self.results_md)

        log.info("[results page]: [%s] [%s]", self.name, results_file)
        return self.results_md
