from .DtnAbstractParser import DtnAbstractParser
from pydantic import validator
from typing import Any, Dict, List, Optional

class DtnNodeParser(DtnAbstractParser):
    """ Parser for DtnNode's YAML configuration parameters """
    # Router type. It must be tag of an element defined in the YAML
    router: str

    # List of generators. Each generator must be a tag in the YAML file
    generators: Optional[List[str]]

    # Outduct selector. It must be a tag in the YAML file
    selector: str

    # List of radios this node carries. Each radio must be a tag in the
    # YAML file
    radios: List[str]

    # Mobility model. If provided, it is because the router needs contact
    # plan data to do its job
    mobility_model: str

    # Endpoints. Equivalent to ports in TCP/IP. It allows you to address
    # a specific part of a node by the EID
    endpoints: Dict[Any, str] = {0: 'DtnDefaultEndpoint'}

    # Time to wait between consecutive limbo pulls in [sec]. If limbo_wait is
    # infinite (default), then you only pull from the limbo when there is something
    # there waiting to be re-routed.
    limbo_wait: float = float('inf')

    @validator('router')
    def validate_router(cls, router, *, values, **kwargs):
        return DtnNodeParser._validate_tag_exitance(cls, router, values)

    @validator('generators')
    def validate_generators(cls, generator, *, values, **kwargs):
        return DtnNodeParser._validate_tag_exitance(cls, generator, values)

    @validator('selector')
    def validate_selector(cls, selector, *, values, **kwargs):
        return DtnNodeParser._validate_tag_exitance(cls, selector, values)

    @validator('radios')
    def validate_radios(cls, radio, *, values, **kwargs):
        return DtnNodeParser._validate_tag_exitance(cls, radio, values)

    @validator('mobility_model')
    def validate_mobility_model(cls, mobility_model, *, values, **kwargs):
        return DtnNodeParser._validate_tag_exitance(cls, mobility_model, values)

    @validator('endpoints', whole=True)
    def validate_endpoints(cls, endpoints, *, values, **kwargs):
        # When validating a dictionary, Pydantic first gives you the keys and
        # values to validate individually. This is currently a known Pydantic
        # bug (see Pydantic github, issue #254)
        if not isinstance(endpoints, dict):
            return endpoints

        # Add default endpoint with the default EID. If the user had specified
        # something else in the 0 EID, it will be overriden
        endpoints[0] = 'DtnDefaultEndpoint'

        return endpoints


        #