#!/usr/bin/env python3
import argparse
import os
import re
from typing import Any, Dict, List, Tuple

import yaml


def main() -> None:
    parser = argparse.ArgumentParser()

    parser.add_argument("--repo", help="Path to the repository", default=".")
    parser.add_argument(
        "--commit",
        help="Commit the changes",
        default=False,
        action="store_true",
    )

    subparsers = parser.add_subparsers()
    subparsers.required = True

    parser_merge = subparsers.add_parser(
        "merge", help="Merge a reference clang-tidy config"
    )
    parser_merge.add_argument(
        "--reference", help="Path to reference clang-tidy", required=True
    )
    parser_merge.set_defaults(func=subcmd_merge)

    parser_enable = subparsers.add_parser(
        "enable", help="Enable a rule in a reference clang-tidy config"
    )
    parser_enable.add_argument("check", help="Check to enable")
    parser_enable.set_defaults(func=subcmd_enable)

    parser_disable = subparsers.add_parser(
        "disable", help="Enable a rule in a reference clang-tidy config"
    )
    parser_disable.add_argument("check", help="Check to disable")
    parser_disable.add_argument(
        "--drop", help="Delete the check from the config", action="store_true"
    )
    parser_disable.set_defaults(func=subcmd_disable)

    args = parser.parse_args()
    args.func(args)


def subcmd_merge(args: argparse.Namespace) -> None:
    repo_path, repo_config = load_config(args.repo)
    ref_path, ref_config = load_config(args.reference)

    result = {}

    all_keys_set = set(repo_config.keys()) | set(ref_config.keys())
    special_keys = ["Checks", "CheckOptions"]

    # Create ordered_keys: special keys first (if present, in their defined order),
    # followed by the rest of the keys sorted alphabetically.
    ordered_keys = [k for k in special_keys if k in all_keys_set] + sorted(
        list(all_keys_set - set(special_keys))
    )

    for key in ordered_keys:
        repo_value = repo_config.get(key)
        ref_value = ref_config.get(key)

        key_class = globals().get(f"Key_{key}")
        if key_class and hasattr(key_class, "merge"):
            result[key] = key_class.merge(repo_value, ref_value)
        elif repo_value:
            result[key] = repo_value
        else:
            result[key] = ref_value

    with open(repo_path, "w") as f:
        f.write(format_yaml_output(result))


def subcmd_enable(args: argparse.Namespace) -> None:
    repo_path, repo_config = load_config(args.repo)

    if "Checks" in repo_config:
        repo_config["Checks"] = Key_Checks.enable(
            repo_config["Checks"], args.check
        )

    with open(repo_path, "w") as f:
        f.write(format_yaml_output(repo_config))

    pass


def subcmd_disable(args: argparse.Namespace) -> None:
    repo_path, repo_config = load_config(args.repo)

    if "Checks" in repo_config:
        repo_config["Checks"] = Key_Checks.disable(
            repo_config["Checks"], args.check, args.drop
        )

    with open(repo_path, "w") as f:
        f.write(format_yaml_output(repo_config))

    pass


class Key_Checks:
    @staticmethod
    def merge(repo: str, ref: str) -> str:
        repo_checks = Key_Checks._split(repo)
        ref_checks = Key_Checks._split(ref)

        result: Dict[str, bool] = {}

        for k, v in repo_checks.items():
            result[k] = v
        for k, v in ref_checks.items():
            if k not in result:
                result[k] = False

        return Key_Checks._join(result)

    @staticmethod
    def enable(repo: str, check: str) -> str:
        repo_checks = Key_Checks._split(repo)
        repo_checks[check] = True
        return Key_Checks._join(repo_checks)

    @staticmethod
    def disable(repo: str, check: str, drop: bool) -> str:
        repo_checks = Key_Checks._split(repo)
        if drop:
            repo_checks.pop(check, None)
        else:
            repo_checks[check] = False
        return Key_Checks._join(repo_checks)

    @staticmethod
    def _split(s: str) -> Dict[str, bool]:
        result: Dict[str, bool] = {}
        if not s:
            return result
        for item in s.split():
            item = item.replace(",", "")
            if "-*" in item:
                continue
            if item.startswith("-"):
                result[item[1:]] = False
            else:
                result[item] = True
        return result

    @staticmethod
    def _join(data: Dict[str, bool]) -> str:
        return (
            ",\n".join(
                ["-*"] + [k if v else f"-{k}" for k, v in sorted(data.items())]
            )
            + "\n"
        )


class Key_CheckOptions:
    @staticmethod
    def merge(
        repo: List[Dict[str, str]], ref: List[Dict[str, str]]
    ) -> List[Dict[str, str]]:
        unrolled_repo: Dict[str, str] = {}
        for item in repo or []:
            unrolled_repo[item["key"]] = item["value"]
        for item in ref or []:
            if item["key"] in unrolled_repo:
                continue
            unrolled_repo[item["key"]] = item["value"]

        return [
            {"key": k, "value": v} for k, v in sorted(unrolled_repo.items())
        ]


def load_config(path: str) -> Tuple[str, Dict[str, Any]]:
    if "clang-tidy" not in path:
        path = os.path.join(path, ".clang-tidy")

    if not os.path.exists(path):
        return (path, {})

    with open(path, "r") as f:
        data = "\n".join([x for x in f.readlines() if not x.startswith("#")])
        return (path, yaml.safe_load(data))


def format_yaml_output(data: Dict[str, Any]) -> str:
    """Convert to a prettier YAML string:
    - filter out excess empty lines
    - insert new lines between keys
    """
    yaml_string = yaml.dump(data, sort_keys=False, indent=4)
    lines: List[str] = []
    for line in yaml_string.split("\n"):
        # Strip excess new lines.
        if not line:
            continue
        # Add new line between keys.
        if len(lines) and re.match("[a-zA-Z0-9]+:", line):
            lines.append("")
        lines.append(line)
    lines.append("")

    return "\n".join(lines)


if __name__ == "__main__":
    main()
