# 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, Union
from pydantic import BaseModel, Field, StrictFloat, StrictInt, StrictStr, confloat, conint, validator

class BicycleCostingOptions(BaseModel):
    """
    BicycleCostingOptions
    """
    maneuver_penalty: Optional[StrictInt] = Field(5, description="A penalty (in seconds) applied when transitioning between roads (determined by name).")
    gate_cost: Optional[StrictInt] = Field(15, description="The estimated cost (in seconds) when a gate is encountered.")
    gate_penalty: Optional[StrictInt] = Field(300, description="A penalty (in seconds) applied to the route cost when a gate is encountered. This penalty can be used to reduce the likelihood of suggesting a route with gates unless absolutely necessary.")
    country_crossing_cost: Optional[StrictInt] = Field(600, description="The estimated cost (in seconds) when encountering an international border.")
    country_crossing_penalty: Optional[StrictInt] = Field(0, description="A penalty applied to transitions to international border crossings. This penalty can be used to reduce the likelihood of suggesting a route with border crossings unless absolutely necessary.")
    service_penalty: Optional[StrictInt] = Field(None, description="A penalty applied to transitions to service roads. This penalty can be used to reduce the likelihood of suggesting a route with service roads unless absolutely necessary. The default penalty is 15 for cars, busses, motor scooters, and motorcycles; and zero for others.")
    service_factor: Optional[Union[StrictFloat, StrictInt]] = Field(1, description="A factor that multiplies the cost when service roads are encountered. The default is 1.2 for cars and busses, and 1 for trucks, motor scooters, and motorcycles.")
    use_living_streets: Optional[Union[confloat(le=1, ge=0, strict=True), conint(le=1, ge=0, strict=True)]] = Field(None, description="A measure of willingness to take living streets. Values near 0 attempt to avoid them, and values near 1 will favour them. Note that as some routes may be impossible without living streets, 0 does not guarantee avoidance of them. The default value is 0 for trucks; 0.1 for other motor vehicles; 0.5 for bicycles; and 0.6 for pedestrians.")
    use_ferry: Optional[Union[confloat(le=1, ge=0, strict=True), conint(le=1, ge=0, strict=True)]] = Field(0.5, description="A measure of willingness to take ferries. Values near 0 attempt to avoid ferries, and values near 1 will favour them. Note that as some routes may be impossible without ferries, 0 does not guarantee avoidance of them.")
    bicycle_type: Optional[StrictStr] = 'Hybrid'
    cycling_speed: Optional[StrictInt] = Field(None, description="The average comfortable travel speed (in kph) along smooth, flat roads. The costing will vary the speed based on the surface, bicycle type, elevation change, etc. This value should be the average sustainable cruising speed the cyclist can maintain over the entire route. The default speeds are as follows based on bicycle type:   * Road - 25kph   * Cross - 20kph   * Hybrid - 18kph   * Mountain - 16kph")
    use_roads: Optional[Union[confloat(le=1, ge=0, strict=True), conint(le=1, ge=0, strict=True)]] = Field(0.5, description="A measure of willingness to use roads alongside other vehicles. Values near 0 attempt to avoid roads and stay on cycleways, and values near 1 indicate the cyclist is more comfortable on roads.")
    use_hills: Optional[Union[confloat(le=1, ge=0, strict=True), conint(le=1, ge=0, strict=True)]] = Field(0.5, description="A measure of willingness to take tackle hills. Values near 0 attempt to avoid hills and steeper grades even if it means a longer route, and values near 1 indicates that the user does not fear them. Note that as some routes may be impossible without hills, 0 does not guarantee avoidance of them.")
    avoid_bad_surfaces: Optional[Union[confloat(le=1, ge=0, strict=True), conint(le=1, ge=0, strict=True)]] = Field(0.25, description="A measure of how much the cyclist wants to avoid roads with poor surfaces relative to the type of bicycle being ridden. When 0, there is no penalization of roads with poorer surfaces, and only bicycle speed is taken into account. As the value approaches 1, roads with poor surfaces relative to the bicycle type receive a heaver penalty, so they will only be taken if they significantly reduce travel time. When the value is 1, all bad surfaces are completely avoided from the route, including the start and end points.")
    bss_return_cost: Optional[StrictInt] = Field(120, description="The estimated cost (in seconds) to return a bicycle in `bikeshare` mode.")
    bss_return_penalty: Optional[StrictInt] = Field(0, description="A penalty (in seconds) to return a bicycle in `bikeshare` mode.")
    additional_properties: Dict[str, Any] = {}
    __properties = ["maneuver_penalty", "gate_cost", "gate_penalty", "country_crossing_cost", "country_crossing_penalty", "service_penalty", "service_factor", "use_living_streets", "use_ferry", "bicycle_type", "cycling_speed", "use_roads", "use_hills", "avoid_bad_surfaces", "bss_return_cost", "bss_return_penalty"]

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

        if value not in ('Road', 'Hybrid', 'Cross', 'Mountain'):
            raise ValueError("must be one of enum values ('Road', 'Hybrid', 'Cross', 'Mountain')")
        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) -> BicycleCostingOptions:
        """Create an instance of BicycleCostingOptions 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)
        # 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) -> BicycleCostingOptions:
        """Create an instance of BicycleCostingOptions from a dict"""
        if obj is None:
            return None

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

        _obj = BicycleCostingOptions.parse_obj({
            "maneuver_penalty": obj.get("maneuver_penalty") if obj.get("maneuver_penalty") is not None else 5,
            "gate_cost": obj.get("gate_cost") if obj.get("gate_cost") is not None else 15,
            "gate_penalty": obj.get("gate_penalty") if obj.get("gate_penalty") is not None else 300,
            "country_crossing_cost": obj.get("country_crossing_cost") if obj.get("country_crossing_cost") is not None else 600,
            "country_crossing_penalty": obj.get("country_crossing_penalty") if obj.get("country_crossing_penalty") is not None else 0,
            "service_penalty": obj.get("service_penalty"),
            "service_factor": obj.get("service_factor") if obj.get("service_factor") is not None else 1,
            "use_living_streets": obj.get("use_living_streets"),
            "use_ferry": obj.get("use_ferry") if obj.get("use_ferry") is not None else 0.5,
            "bicycle_type": obj.get("bicycle_type") if obj.get("bicycle_type") is not None else 'Hybrid',
            "cycling_speed": obj.get("cycling_speed"),
            "use_roads": obj.get("use_roads") if obj.get("use_roads") is not None else 0.5,
            "use_hills": obj.get("use_hills") if obj.get("use_hills") is not None else 0.5,
            "avoid_bad_surfaces": obj.get("avoid_bad_surfaces") if obj.get("avoid_bad_surfaces") is not None else 0.25,
            "bss_return_cost": obj.get("bss_return_cost") if obj.get("bss_return_cost") is not None else 120,
            "bss_return_penalty": obj.get("bss_return_penalty") if obj.get("bss_return_penalty") is not None else 0
        })
        # 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

