from __future__ import annotations

from typing import Any, Mapping

from xdatawork.connect.connectkind import ConnectKind
from xdatawork.connect.connectreflike import ConnectRefLike


class ConnectRef(ConnectRefLike):
    """
    描述:
    - 连接引用数据类，表示存储对象的位置引用。
    - 包含位置信息和可选的类型标识。
    - 支持从字典创建和序列化为字典。
    - 实现了相等性比较和哈希方法。

    属性:
    - location: 存储位置字符串。
    - kind: 连接类型（如 's3', 'macos' 等）。
    例子:
    ```python
        from xdatawork.connect.connectref import ConnectRef
        from xdatawork.connect.connectkind import ConnectKind

        # 创建引用
        ref = ConnectRef(location="s3://bucket/key", kind=ConnectKind.S3)

        # 从字典创建
        ref2 = ConnectRef.from_dict({"location": "path/to/file", "kind": "macos"})

        # 序列化
        data = ref.to_dict()

        # 比较
        assert ref == ConnectRef(location="s3://bucket/key", kind=ConnectKind.S3)
    ```
    """

    @classmethod
    def from_dict(cls, data: Mapping[str, Any]) -> ConnectRef:
        if "location" not in data:
            raise KeyError("'location' is required in data")
        location = data["location"]
        kindtext = data.get("kind")
        kind = ConnectKind.from_any(kindtext) if kindtext else None
        return cls(location=location, kind=kind)

    def __init__(
        self,
        location: str,
        kind: ConnectKind | str | None = None,
    ) -> None:
        self.location = location
        self.kind = self._resolve_kind(kind)

    def _resolve_kind(
        self,
        kind: ConnectKind | None,
    ) -> ConnectKind | None:
        if kind is None:
            return None
        else:
            return ConnectKind.from_any(kind)

    def __eq__(self, other: object) -> bool:
        if not isinstance(other, ConnectRef):
            return NotImplemented
        return self.location == other.location and self.kind == other.kind

    def __hash__(self) -> int:
        return hash((self.location, self.kind))

    def __str__(self) -> str:
        return f"{self.location}"

    def __repr__(self) -> str:
        return f"{self.__class__.__name__}(location={self.location}, kind={self.kind})"

    def to(self, rel: str) -> ConnectRef:
        old = self.location.rstrip("/")
        rel = rel.lstrip("/")
        return ConnectRef(
            location=f"{old}/{rel}",
            kind=self.kind,
        )

    def describe(self) -> dict[str, str | None]:
        result = {"location": self.location}
        if self.kind is not None:
            result["kind"] = self.kind.value
        return result

    def to_dict(self) -> dict[str, str | None]:
        result = {"location": self.location}
        if self.kind is not None:
            result["kind"] = self.kind.value
        return result
