from abc import ABC
from typing import Optional, Type, get_origin, get_args

from core.get_value import get_value
from core.typing import T


class InputABC(ABC):
    def __init__(
        self,
        src: Optional[dict],
    ):
        ABC.__init__(self)
        self._src = src

        self._options = {}

    def option(
        self, field: str, cast_type: Type[T], default=None, required=False
    ) -> Optional[T]:
        if required and field not in self._src:
            raise ValueError(f"{field} is required")

        self._options[field] = cast_type
        if field not in self._src:
            return default

        value = self._src[field]
        if get_origin(cast_type) == list:
            sub_type = get_args(cast_type)[0]
            return [sub_type(item) for item in value]

        return cast_type(value)

    def get(self, field: str, default=None) -> Optional[T]:
        return get_value(self._src, field, self._options[field], default)
