#!/usr/bin/env python3
# Copyright: 2016, Maximiliano Curia <maxy@debian.org>
#
# License: ISC
#  Permission to use, copy, modify, and/or distribute this software for any
#  purpose with or without fee is hereby granted, provided that the above
#  copyright notice and this permission notice appear in all copies.
#  .
#  THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
#  REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
#  AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
#  INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
#  LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
#  OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
#  PERFORMANCE OF THIS SOFTWARE.

"""
Group interface and data contracts extracted from dep5.py

This module defines the interfaces and data structures that Group classes
must implement, enabling better separation of concerns and testing.
"""

from __future__ import annotations

import collections.abc as abc
import typing as t

import debian.copyright as dc

from decopy.common.core_types import CopyrightHolder, License, Options

if t.TYPE_CHECKING:
    from decopy.fstree.nodes import FileInfo
    from decopy.grouping.group import FileGroup
    from decopy.grouping.grouping import GroupKey
    from decopy.licensing.holders import CopyrightHolders
    from decopy.licensing.license_expr import Node


@t.runtime_checkable
class LicenseKeyed(t.Protocol):
    """Something that can report a license key - a Group, seen from a file.

    This is the only part of a group a FileInfo needs from its existing_group,
    so that field depends on this rather than on the full GroupProtocol.
    """

    def get_license_key(self) -> str:
        """Get the license key."""
        ...


@t.runtime_checkable
class GroupProtocol(LicenseKeyed, t.Protocol):
    """
    Protocol defining the interface that all Group classes must implement.

    This protocol allows for different Group implementations while
    maintaining a consistent interface.
    """

    @property
    def license(self) -> str: ...

    @property
    def license_field(self) -> str: ...

    license_expr: Node | None
    key: GroupKey | None
    position: int
    files: FileGroup
    copyrights: CopyrightHolders
    declared_copyright_key: tuple[str, ...]
    licenses: dict[str, License]
    license_filenames: set[str]
    comments: list[str]
    stored: dc.FilesParagraph | None

    def add_file(self, fileinfo: FileInfo) -> None:
        """Add a file to this group."""
        ...

    def add_copyrights(self, copyrights: abc.Iterable[CopyrightHolder]) -> None:
        """Add copyrights to this group."""
        ...

    def get_key(
        self,
        options: Options,
        *,
        ignore_copyright: bool = False,
    ) -> GroupKey:
        """Get the key for this group based on options."""
        ...

    def copyright_block_valid(self) -> bool:
        """Check if this group can generate a valid copyright block."""
        ...

    def get_comments(self) -> str:
        """Get the assembled comment text for this group."""
        ...

    def extra_fields(self) -> abc.Iterable[tuple[str, str]]:
        """Yield the stored paragraph's non-standard (name, value) fields."""
        ...

    def sort_key(self, options: Options) -> tuple[int, int, int, int, t.Any]:
        """Get the sort key for this group."""
        ...
