#!/usr/bin/env python3
#
# Copyright (c) 2020 Arm Limited
# All rights reserved
#
# The license below extends only to copyright in the software and shall
# not be construed as granting a license to any other intellectual
# property including but not limited to intellectual property relating
# to a hardware implementation of the functionality of the software
# licensed hereunder.  You may use the software subject to the license
# terms below provided that you ensure that this notice is replicated
# unmodified and in its entirety in all distributions of the software,
# modified or unmodified, in source code or in binary form.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met: redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer;
# redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution;
# neither the name of the copyright holders nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import email.utils
import enum
import os
from typing import (
    Any,
    Dict,
    Iterator,
    List,
    Mapping,
    Optional,
    Sequence,
    TextIO,
    Tuple,
    Union,
)

import yaml

PathOrFile = Union[TextIO, str]


class FileFormatException(Exception):
    pass


class MissingFieldException(FileFormatException):
    pass


class IllegalValueException(FileFormatException):
    pass


class Status(enum.Enum):
    MAINTAINED = enum.auto()
    ORPHANED = enum.auto()

    @classmethod
    def from_str(cls, key: str) -> "Status":
        _status_dict = {"maintained": cls.MAINTAINED, "orphaned": cls.ORPHANED}
        return _status_dict[key]

    def __str__(self) -> str:
        return {Status.MAINTAINED: "maintained", Status.ORPHANED: "orphaned"}[
            self
        ]


class Subsystem(object):
    tag: str
    status: Status
    maintainers: List[Tuple[str, str]]  # Name, email
    description: str

    def __init__(
        self,
        tag: str,
        maintainers: Optional[Sequence[Tuple[str, str]]],
        description: str = "",
        status: Status = Status.ORPHANED,
    ):
        self.tag = tag
        self.status = status
        self.maintainers = list(maintainers) if maintainers is not None else []
        self.description = description if description is not None else ""


class Maintainers(object):
    DEFAULT_MAINTAINERS = os.path.join(
        os.path.dirname(__file__), "../../../MAINTAINERS.yaml"
    )

    _subsystems: Dict[str, Subsystem]  # tag -> Subsystem

    def __init__(self, ydict: Mapping[str, Any]):
        self._subsystems = {}
        for tag, maint in list(ydict.items()):
            self._subsystems[tag] = Maintainers._parse_subsystem(tag, maint)

    @classmethod
    def from_file(
        cls, path_or_file: Optional[PathOrFile] = None
    ) -> "Maintainers":

        return cls(Maintainers._load_maintainers_file(path_or_file))

    @classmethod
    def from_yaml(cls, yaml_str: str) -> "Maintainers":
        return cls(yaml.load(yaml_str, Loader=yaml.SafeLoader))

    @classmethod
    def _load_maintainers_file(
        cls, path_or_file: Optional[PathOrFile] = None
    ) -> Mapping[str, Any]:
        if path_or_file is None:
            path_or_file = cls.DEFAULT_MAINTAINERS

        if isinstance(path_or_file, str):
            with open(path_or_file, "r") as fin:
                return yaml.load(fin, Loader=yaml.SafeLoader)
        else:
            return yaml.load(path_or_file, Loader=yaml.SafeLoader)

    @classmethod
    def _parse_subsystem(cls, tag: str, ydict: Mapping[str, Any]) -> Subsystem:
        def required_field(name):
            try:
                return ydict[name]
            except KeyError:
                raise MissingFieldException(
                    f"{tag}: Required field '{name}' is missing"
                )

        maintainers: List[Tuple[str, str]] = []
        raw_maintainers = ydict.get("maintainers", [])
        if not isinstance(raw_maintainers, Sequence):
            raise IllegalValueException(
                f"{tag}: Illegal field 'maintainers' isn't a list."
            )
        for maintainer in raw_maintainers:
            name, address = email.utils.parseaddr(maintainer)
            if name == "" and address == "":
                raise IllegalValueException(
                    f"{tag}: Illegal maintainer field: '{maintainer}'"
                )
            maintainers.append((name, address))

        try:
            status = Status.from_str(required_field("status"))
        except KeyError:
            raise IllegalValueException(
                f"{tag}: Invalid status '{ydict['status']}'"
            )

        return Subsystem(
            tag,
            maintainers=maintainers,
            status=status,
            description=ydict.get("desc", ""),
        )

    def __iter__(self) -> Iterator[Tuple[str, Subsystem]]:
        return iter(list(self._subsystems.items()))

    def __getitem__(self, key: str) -> Subsystem:
        return self._subsystems[key]


def _main():
    maintainers = Maintainers.from_file()
    for tag, subsys in maintainers:
        print(f"{tag}: {subsys.description}")
        print(f"  Status: {subsys.status}")
        print(f"  Maintainers:")
        for maint in subsys.maintainers:
            print(f"    - {maint[0]} <{maint[1]}>")
        print()


if __name__ == "__main__":
    _main()

__all__ = [
    "FileFormatException",
    "MissingFieldException",
    "IllegalValueException",
    "Status",
    "Subsystem",
    "Maintainers",
]
