#!/usr/bin/env python

#
#    Copyright (c) 2022 Project CHIP Authors
#    All rights reserved.
#
#    Licensed under the Apache License, Version 2.0 (the "License");
#    you may not use this file except in compliance with the License.
#    You may obtain a copy of the License at
#
#        http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS,
#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#    See the License for the specific language governing permissions and
#    limitations under the License.
#

#
# Execute as `python scripts/error_table.py > docs/ERROR_CODES.md` from root of repos
#
# This script uses heuristics scraping of the headers to generate nice tables
#

import re
from dataclasses import dataclass
from enum import IntEnum
from pathlib import Path
from operator import attrgetter
from xml.etree.ElementInclude import include


@dataclass
class ErrorCode:
    code: int
    name: str
    description: str


@dataclass
class ErrorDescriptor:
    section: str
    code_range: int
    # `macro_regex` needs to have `code` and `name` named groups.
    macro_regex: str
    include_description: bool = False


class CommentState(IntEnum):
    WAIT_START_COMMENT = 0
    ACCUMULATE_COMMENT = 1


class ErrorCodeLoader:
    def __init__(self) -> None:
        self.reset()

    def reset(self):
        self._comment_state = CommentState.WAIT_START_COMMENT
        self._last_comment = []
        self._error_codes: list[ErrorCode] = []

    def _process_comment_extract(self, line):
        if self._comment_state == CommentState.WAIT_START_COMMENT:
            if "/**" in line:
                self._last_comment = []
                self._comment_state = CommentState.ACCUMULATE_COMMENT
        elif self._comment_state == CommentState.ACCUMULATE_COMMENT:
            if "*/" in line:
                self._comment_state = CommentState.WAIT_START_COMMENT
            else:
                self._last_comment.append(line)

    def _process_error_extract(self, descriptor: ErrorDescriptor, line: str):
        match = re.search(descriptor.macro_regex, line)
        if match is None:
            return

        last_comment = "".join(self._last_comment).replace("   ", " ").replace("  ", " ").replace("*", "").replace(".", "")
        last_comment = last_comment.split("@brief")[-1].strip()

        code = int(match.group("code"), 0)
        code = descriptor.code_range | code
        name = match.group("name")

        description = last_comment if descriptor.include_description else ""
        self._error_codes.append(ErrorCode(code=code, name=name, description=description))

    def load_error_header(self, filename: Path, descriptor: ErrorDescriptor) -> list[ErrorCode]:
        self.reset()

        lines = filename.read_text().split("\n")
        for line in lines:
            line = line.strip()
            self._process_comment_extract(line)
            self._process_error_extract(descriptor, line)

        return self._error_codes


def get_section_title(section: str) -> tuple[str, str]:
    markdown_title = f"{section} errors"
    anchor_name = f'#{markdown_title.lower().replace(" ","-").replace(".","-")}'

    return markdown_title, anchor_name


def dump_table(header_path: Path, descriptor: ErrorDescriptor):
    loader = ErrorCodeLoader()
    codes_for_section = loader.load_error_header(header_path, descriptor)

    markdown_title, _ = get_section_title(descriptor.section)
    print(f"## {markdown_title}")
    print()
    if descriptor.include_description:
        print("| Decimal | Hex |  Name | Description |")
        print("| --- | --- | --- | --- |")
    else:
        print("| Decimal | Hex |  Name |")
        print("| --- | --- | --- |")

    for code in sorted(codes_for_section, key=attrgetter("code")):
        if descriptor.include_description:
            print(f"| {code.code} | 0x{code.code:02X} | `{code.name}` | {code.description} |")
        else:
            print(f"| {code.code} | 0x{code.code:02X} | `{code.name}` |")

    print()


def main():
    descriptors = {
        "src/lib/core/CHIPError.h": ErrorDescriptor(section="SDK Core", code_range=0x000, macro_regex=r"^#define\s+(?P<name>[_A-Z0-9]+)\s+CHIP(_CORE)?_ERROR[(](?P<code>(0x[a-fA-F0-9]+)|\d+)[)]"),
        "src/inet/InetError.h": ErrorDescriptor(section="SDK Inet Layer", code_range=0x100, macro_regex=r"^#define\s+(?P<name>[_A-Z0-9]+)\s+CHIP_INET_ERROR[(](?P<code>(0x[a-fA-F0-9]+)|\d+)[)]"),
        "src/include/platform/CHIPDeviceError.h": ErrorDescriptor(section="SDK Device Layer", code_range=0x200, macro_regex=r"^#define\s+(?P<name>[_A-Z0-9]+)\s+CHIP_DEVICE_ERROR[(](?P<code>(0x[a-fA-F0-9]+)|\d+)[)]"),
        "src/lib/asn1/ASN1Error.h": ErrorDescriptor(section="ASN.1 Layer", code_range=0x300, macro_regex=r"^#define\s+(?P<name>[_A-Z0-9]+)\s+CHIP_ASN1_ERROR[(](?P<code>(0x[a-fA-F0-9]+)|\d+)[)]"),
        "src/ble/BleError.h": ErrorDescriptor(section="BLE Layer", code_range=0x400, macro_regex=r"^#define\s+(?P<name>[_A-Z0-9]+)\s+CHIP_BLE_ERROR[(](?P<code>(0x[a-fA-F0-9]+)|\d+)[)]"),
        "src/protocols/interaction_model/StatusCodeList.h": ErrorDescriptor(section="IM Global errors", code_range=0x500, macro_regex=r"^CHIP_IM_STATUS_CODE[(][A-Za-z0-9_]+\s*,\s*(?P<name>[A-Z0-9_]+)\s*,\s*(?P<code>(0x[a-fA-F0-9]+)|\d+)[)]"),
    }

    print()
    print("[//]: # (start_ignore_spellcheck)")
    print()
    print("# Matter SDK `CHIP_ERROR` enums values")
    print()
    print("This file was **AUTOMATICALLY** generated by `python scripts/error_table.py > docs/ERROR_CODES.md`.")
    print("DO NOT EDIT BY HAND!")
    print()
    print("## Table of contents")

    for descriptor in descriptors.values():
        markdown_title, anchor_name = get_section_title(descriptor.section)
        print(f"- [{markdown_title}: range `0x{descriptor.code_range:03X}..0x{descriptor.code_range | 0xFF:03X}`]({anchor_name})")
    print()

    for filename, descriptor in descriptors.items():
        dump_table(Path(filename), descriptor)

    print("[//]: # (end_ignore_spellcheck)")


if __name__ == "__main__":
    main()
