# coding: utf-8

"""
    Stadia Maps Geospatial APIs

    The Stadia Maps Geospatial APIs provide you with the data you need to build awesome applications.  # noqa: E501

    The version of the OpenAPI document: 5.0.4
    Contact: support@stadiamaps.com
    Generated by OpenAPI Generator (https://openapi-generator.tech)

    Do not edit the class manually.
"""


from __future__ import annotations
import pprint
import re  # noqa: F401
import json


from typing import Optional
from pydantic import BaseModel, Field, StrictBool, StrictInt, StrictStr, validator
from stadiamaps.models.geo_attributes import GeoAttributes
from stadiamaps.models.highway_classification import HighwayClassification
from stadiamaps.models.node_id import NodeId
from stadiamaps.models.restrictions import Restrictions
from stadiamaps.models.speeds import Speeds

class LocateDetailedEdge(BaseModel):
    """
    LocateDetailedEdge
    """
    sidewalk_left: Optional[StrictBool] = Field(None, description="Is there a sidewalk to the left of the edge?")
    sidewalk_right: Optional[StrictBool] = Field(None, description="Is there a sidewalk to the right of the edge?")
    lane_count: Optional[StrictInt] = None
    stop_sign: Optional[StrictBool] = Field(None, description="Is there a stop sign at end of the directed edge?")
    sac_scale: Optional[StrictStr] = None
    yield_sign: Optional[StrictBool] = Field(None, description="Is there a yield sign at end of the directed edge?")
    not_thru: Optional[StrictBool] = Field(None, description="Does the edge lead to a \"no-through\" region?")
    forward: Optional[StrictBool] = Field(None, description="Is the edge info forward? If false, then reverse is implied.")
    end_node: Optional[NodeId] = None
    truck_route: Optional[StrictBool] = Field(None, description="Is the edge part of a truck route/network?")
    speeds: Optional[Speeds] = None
    bike_network: Optional[StrictBool] = Field(None, description="Is the edge part of a bicycle network?")
    round_about: Optional[StrictBool] = Field(None, description="Is the edge part of a roundabout?")
    traffic_signal: Optional[StrictBool] = Field(None, description="Is there a traffic signal at the end of the directed edge?")
    access_restriction: Optional[StrictBool] = Field(None, description="Is there a general restriction or access condition?")
    destination_only: Optional[StrictBool] = Field(None, description="Is the edge destination only? If so, it will not be routed through.")
    geo_attributes: Optional[GeoAttributes] = None
    start_restriction: Optional[Restrictions] = None
    cycle_lane: Optional[StrictStr] = Field(None, description="Indication of the type of cycle lane (if any) present along an edge.")
    end_restriction: Optional[Restrictions] = None
    seasonal: Optional[StrictBool] = Field(None, description="Is access seasonal (ex. no access in winter)?")
    country_crossing: Optional[StrictBool] = Field(None, description="Does the edge cross into a new country?")
    part_of_complex_restriction: Optional[StrictBool] = Field(None, description="Is the edge part of a complex restriction?")
    has_sign: Optional[StrictBool] = Field(None, description="Do exit signs exist for the edge?")
    access: Optional[Restrictions] = None
    bridge: Optional[StrictBool] = Field(None, description="Is the edge part of a bridge?")
    classification: Optional[HighwayClassification] = None
    toll: Optional[StrictBool] = Field(None, description="Is the edge part of a toll road?")
    tunnel: Optional[StrictBool] = Field(None, description="Is the edge part of a tunnel?")
    additional_properties: Dict[str, Any] = {}
    __properties = ["sidewalk_left", "sidewalk_right", "lane_count", "stop_sign", "sac_scale", "yield_sign", "not_thru", "forward", "end_node", "truck_route", "speeds", "bike_network", "round_about", "traffic_signal", "access_restriction", "destination_only", "geo_attributes", "start_restriction", "cycle_lane", "end_restriction", "seasonal", "country_crossing", "part_of_complex_restriction", "has_sign", "access", "bridge", "classification", "toll", "tunnel"]

    @validator('sac_scale')
    def sac_scale_validate_enum(cls, value):
        """Validates the enum"""
        if value is None:
            return value

        if value not in ('none', 'hiking', 'mountain hiking', 'demanding mountain hiking', 'alpine hiking', 'demanding alpine hiking', 'difficult alpine hiking'):
            raise ValueError("must be one of enum values ('none', 'hiking', 'mountain hiking', 'demanding mountain hiking', 'alpine hiking', 'demanding alpine hiking', 'difficult alpine hiking')")
        return value

    @validator('cycle_lane')
    def cycle_lane_validate_enum(cls, value):
        """Validates the enum"""
        if value is None:
            return value

        if value not in ('none', 'shared', 'dedicated', 'separated'):
            raise ValueError("must be one of enum values ('none', 'shared', 'dedicated', 'separated')")
        return value

    class Config:
        """Pydantic configuration"""
        allow_population_by_field_name = True
        validate_assignment = True

    def to_str(self) -> str:
        """Returns the string representation of the model using alias"""
        return pprint.pformat(self.dict(by_alias=True))

    def to_json(self) -> str:
        """Returns the JSON representation of the model using alias"""
        return json.dumps(self.to_dict())

    @classmethod
    def from_json(cls, json_str: str) -> LocateDetailedEdge:
        """Create an instance of LocateDetailedEdge from a JSON string"""
        return cls.from_dict(json.loads(json_str))

    def to_dict(self):
        """Returns the dictionary representation of the model using alias"""
        _dict = self.dict(by_alias=True,
                          exclude={
                            "additional_properties"
                          },
                          exclude_none=True)
        # override the default output from pydantic by calling `to_dict()` of end_node
        if self.end_node:
            _dict['end_node'] = self.end_node.to_dict()
        # override the default output from pydantic by calling `to_dict()` of speeds
        if self.speeds:
            _dict['speeds'] = self.speeds.to_dict()
        # override the default output from pydantic by calling `to_dict()` of geo_attributes
        if self.geo_attributes:
            _dict['geo_attributes'] = self.geo_attributes.to_dict()
        # override the default output from pydantic by calling `to_dict()` of start_restriction
        if self.start_restriction:
            _dict['start_restriction'] = self.start_restriction.to_dict()
        # override the default output from pydantic by calling `to_dict()` of end_restriction
        if self.end_restriction:
            _dict['end_restriction'] = self.end_restriction.to_dict()
        # override the default output from pydantic by calling `to_dict()` of access
        if self.access:
            _dict['access'] = self.access.to_dict()
        # override the default output from pydantic by calling `to_dict()` of classification
        if self.classification:
            _dict['classification'] = self.classification.to_dict()
        # puts key-value pairs in additional_properties in the top level
        if self.additional_properties is not None:
            for _key, _value in self.additional_properties.items():
                _dict[_key] = _value

        return _dict

    @classmethod
    def from_dict(cls, obj: dict) -> LocateDetailedEdge:
        """Create an instance of LocateDetailedEdge from a dict"""
        if obj is None:
            return None

        if not isinstance(obj, dict):
            return LocateDetailedEdge.parse_obj(obj)

        _obj = LocateDetailedEdge.parse_obj({
            "sidewalk_left": obj.get("sidewalk_left"),
            "sidewalk_right": obj.get("sidewalk_right"),
            "lane_count": obj.get("lane_count"),
            "stop_sign": obj.get("stop_sign"),
            "sac_scale": obj.get("sac_scale"),
            "yield_sign": obj.get("yield_sign"),
            "not_thru": obj.get("not_thru"),
            "forward": obj.get("forward"),
            "end_node": NodeId.from_dict(obj.get("end_node")) if obj.get("end_node") is not None else None,
            "truck_route": obj.get("truck_route"),
            "speeds": Speeds.from_dict(obj.get("speeds")) if obj.get("speeds") is not None else None,
            "bike_network": obj.get("bike_network"),
            "round_about": obj.get("round_about"),
            "traffic_signal": obj.get("traffic_signal"),
            "access_restriction": obj.get("access_restriction"),
            "destination_only": obj.get("destination_only"),
            "geo_attributes": GeoAttributes.from_dict(obj.get("geo_attributes")) if obj.get("geo_attributes") is not None else None,
            "start_restriction": Restrictions.from_dict(obj.get("start_restriction")) if obj.get("start_restriction") is not None else None,
            "cycle_lane": obj.get("cycle_lane"),
            "end_restriction": Restrictions.from_dict(obj.get("end_restriction")) if obj.get("end_restriction") is not None else None,
            "seasonal": obj.get("seasonal"),
            "country_crossing": obj.get("country_crossing"),
            "part_of_complex_restriction": obj.get("part_of_complex_restriction"),
            "has_sign": obj.get("has_sign"),
            "access": Restrictions.from_dict(obj.get("access")) if obj.get("access") is not None else None,
            "bridge": obj.get("bridge"),
            "classification": HighwayClassification.from_dict(obj.get("classification")) if obj.get("classification") is not None else None,
            "toll": obj.get("toll"),
            "tunnel": obj.get("tunnel")
        })
        # store additional fields in additional_properties
        for _key in obj.keys():
            if _key not in cls.__properties:
                _obj.additional_properties[_key] = obj.get(_key)

        return _obj

