# Copyright (C) 2022-2023 HERE Global B.V. and its affiliate(s).
# All rights reserved.
#
# This software and other materials contain proprietary information
# controlled by HERE and are protected by applicable copyright legislation.
# Any use and utilization of this software and other materials and
# disclosure to any third parties is conditional upon having a separate
# agreement with HERE for the access, use, utilization or disclosure of this
# software. In the absence of such agreement, the use of the software is not
# allowed.

"""
Models for the HMC Layers.
"""

from dataclasses import dataclass
from typing import List, Optional

from geojson import MultiPolygon, Point
from here.content.base import ContentIndexer
from here.platform.adapter import DecodedMessage, Identifier, Partition, Ref


class DTO:
    """Object to carry dynamic data to pass to parser functions."""

    def __init__(self, **kwargs):
        """Initializes object with keyword arguments `:param:kwargs`"""

        self.__dict__ = kwargs


@dataclass
class Name:
    """Names Details."""

    text: DecodedMessage
    type: str
    representation: Optional[List[DecodedMessage]] = None
    primary: Optional[DecodedMessage] = None


@dataclass
class Supplier:
    """Supplier Details."""

    partition_id: Partition
    id: Identifier
    names: List[Name]
    category: Ref

    indexer = ContentIndexer(partition="partition_id", identifier="id")


@dataclass
class Author:
    """Author Details."""

    partition_id: Partition
    value: DecodedMessage

    indexer = ContentIndexer(partition="partition_id")


@dataclass
class Place:
    """Place Details."""

    partition_id: Partition
    id: Identifier
    names: List[Name]
    location: Ref
    categories: Optional[List[Ref]] = None
    alt_categories: Optional[List[Ref]] = None
    political_view_name_replacement: Optional[List[DecodedMessage]] = None
    political_view_action: Optional[List[DecodedMessage]] = None
    valid_unnamed: Optional[DecodedMessage] = None

    indexer = ContentIndexer(partition="partition_id", identifier="id")


@dataclass
class ExternalIdentifier:
    """External Identifier Details."""

    partition_id: Partition
    id: Identifier
    places: List[Place]
    supplier: Supplier
    inactive: bool
    category: Ref
    type: str

    indexer = ContentIndexer(partition="partition_id", identifier="id")


@dataclass
class ContactAdditionalData:
    """Additional Data in Contact."""

    key: str
    value: str
    language_code: str
    language_type: str


@dataclass
class Contact:
    """Contact Details."""

    type: str
    value: str
    preferred: bool
    category: Optional[Ref] = None
    label: Optional[DecodedMessage] = None
    country_code: Optional[int] = None
    additional_data: Optional[List[ContactAdditionalData]] = None


@dataclass
class ContactInformation:
    """Contact Information Details."""

    partition_id: Partition
    places: List[Place]
    contacts: List[Contact]

    indexer = ContentIndexer(partition="partition_id")


@dataclass
class Time:
    """Time in Seconds and Nanos."""

    seconds: int
    nanos: int


@dataclass
class TimeRange:
    """Time Range with Start and End Time of the Day."""

    start_time_of_day: Time
    end_time_of_day: Time


@dataclass
class OperationTime:
    """Operation Time Details."""

    excluded: bool
    approx_seasonal_range: bool
    days_of_week: List[str]
    time_range: TimeRange


@dataclass
class OperatingTime:
    """Operating Time Details."""

    partition_id: Partition
    places: List[Place]
    operation_times: List[OperationTime]
    open24x7: bool
    categories: Optional[List[Ref]] = None
    additional_data: Optional[List[DecodedMessage]] = None

    indexer = ContentIndexer(partition="partition_id")


@dataclass
class Feedback:
    """Feedback Details."""

    partition_id: Partition
    value: DecodedMessage

    indexer = ContentIndexer(partition="partition_id")


@dataclass
class Payment:
    """Payment Details."""

    partition_id: Partition
    places: List[Place]
    type_qualifier: List[str]
    type: str
    accepted: bool

    indexer = ContentIndexer(partition="partition_id")


@dataclass
class Relationship:
    """Relationship Details."""

    references: List[DecodedMessage]
    type: str
    primary: bool
    system: str
    name: str
    id: str


@dataclass
class RelationshipAttribute:
    """Releation Attribute Details."""

    partition_id: Partition
    places: List[Place]
    relationships: List[Relationship]

    indexer = ContentIndexer(partition="partition_id")


@dataclass
class CapacityAttribute:
    """Capacity Details."""

    partition_id: Partition
    value: DecodedMessage

    indexer = ContentIndexer(partition="partition_id")


@dataclass
class InternetConnectionAttribute:
    """Internet Connection Details."""

    partition_id: Partition
    value: DecodedMessage

    indexer = ContentIndexer(partition="partition_id")


@dataclass
class Qualifier:
    """Qualifier for Price Range."""

    value: str
    language: str


@dataclass
class PriceRange:
    """Price Range Details."""

    partition_id: Partition
    places: List[Place]
    qualifiers: List[Qualifier]
    notes: List[DecodedMessage]
    min_range: float
    max_range: float
    currency_type: str

    indexer = ContentIndexer(partition="partition_id")


@dataclass
class SpokenLanguage:
    """Spoken Language Details."""

    partition_id: Partition
    value: DecodedMessage

    indexer = ContentIndexer(partition="partition_id")


@dataclass
class QrCodeAttribute:
    """QR Code Details."""

    partition_id: Partition
    value: DecodedMessage

    indexer = ContentIndexer(partition="partition_id")


@dataclass
class Verification:
    """Verification Details."""

    attributes: List[str]
    method: str
    status: str
    type: str
    system: str
    verified: str
    start_date: str
    end_date: str
    expiration_date: str


@dataclass
class VerificationAttribute:
    """Verification Attribute Details."""

    partition_id: Partition
    places: List[Place]
    verifications: List[Verification]

    indexer = ContentIndexer(partition="partition_id")


@dataclass
class MediaReference:
    """Media Reference Details."""

    labels: List[str]
    url: str
    type: str
    id: Optional[str] = None


@dataclass
class MediaReferenceAttribute:
    """Media Reference Attribute Details."""

    partition_id: Partition
    places: List[Place]
    media_refs: List[MediaReference]

    indexer = ContentIndexer(partition="partition_id")


@dataclass
class QualityScore:
    """Quality Score Details."""

    partition_id: Partition
    places: List[Place]
    overall_confidence: str
    place_confidence: str
    open_confidence: str
    address_confidence: str
    name_confidence: str
    phone_confidence: str
    model_version: str
    place_quality_level: str
    open_quality_level: str
    address_quality_level: str
    name_quality_level: str
    phone_quality_level: str
    reality_confidence: str
    reality_quality_level: str
    category: Optional[Ref] = None

    indexer = ContentIndexer(partition="partition_id")


@dataclass
class PlaceAccessAttribute:
    """Place Access Details."""

    partition_id: Partition
    places: List[Place]
    group_restrictions: List[DecodedMessage]
    dogs_allowed: bool
    handicap_accessible: str
    private_access: bool
    category: Optional[Ref] = None

    indexer = ContentIndexer(partition="partition_id")


@dataclass
class AlcoholServiceAttribute:
    """Alcohol Service Details."""

    partition_id: Partition
    places: List[Place]
    alcohol_notes: List[DecodedMessage]
    beer: bool
    wine: bool
    liquor: bool
    category: Optional[Ref] = None

    indexer = ContentIndexer(partition="partition_id")


@dataclass
class AmenitiesAttribute:
    """Amenities Details."""

    partition_id: Partition
    places: List[Place]
    air_conditioning: Optional[bool] = False
    elevators: Optional[bool] = False
    escalators: Optional[bool] = False
    family_friendly: Optional[bool] = False
    onsite_heart_defribillator: Optional[bool] = False
    restrooms_available: Optional[bool] = False
    security_guard: Optional[bool] = False
    smoking: Optional[bool] = False
    television: Optional[bool] = False
    seating_options: Optional[str] = None
    seating_capacity: Optional[str] = None
    category: Optional[Ref] = None

    indexer = ContentIndexer(partition="partition_id")


@dataclass
class BasicInfoAttribute:
    """Basic Information."""

    partition_id: Partition
    places: List[Place]
    access_type: Optional[str] = None
    building_type: Optional[str] = None
    capital_indicator: Optional[str] = None
    capital_level: Optional[str] = None
    population: Optional[str] = None
    category: Optional[Ref] = None

    indexer = ContentIndexer(partition="partition_id")


@dataclass
class OtherInformation:
    """Other Information."""

    partition_id: Partition
    places: List[Place]
    additional_notes: List[DecodedMessage]
    national_importance: bool
    category: Optional[Ref] = None

    indexer = ContentIndexer(partition="partition_id")


@dataclass
class ElectricChargeAttribute:
    """Electric Charge Details."""

    partition_id: Partition
    value: DecodedMessage

    indexer = ContentIndexer(partition="partition_id")


@dataclass
class HotelAttribute:
    """Hotel Details."""

    partition_id: Partition
    places: List[Place]
    breakfast_included: Optional[bool] = False
    conference_hall: Optional[bool] = False
    handicap_rooms: Optional[bool] = False
    hot_tub: Optional[bool] = False
    sauna: Optional[bool] = False
    spa: Optional[bool] = False
    sports_infrastructure: Optional[bool] = False
    swimming: Optional[bool] = False
    swimming_pool: Optional[bool] = False
    swimming_pool_indoor: Optional[bool] = False
    swimming_pool_outdoor: Optional[bool] = False
    category: Optional[Ref] = None

    indexer = ContentIndexer(partition="partition_id")


@dataclass
class LocationInformation:
    """Location Information Details."""

    partition_id: Partition
    value: DecodedMessage

    indexer = ContentIndexer(partition="partition_id")


@dataclass
class ParkingAttribute:
    """Parking Details."""

    partition_id: Partition
    value: DecodedMessage

    indexer = ContentIndexer(partition="partition_id")


@dataclass
class RestaurantAttribute:
    """Restaurant Details."""

    partition_id: Partition
    places: List[Place]
    beer_selections: Optional[List[DecodedMessage]] = None
    cooking_types: Optional[List[DecodedMessage]] = None
    specialities: Optional[List[DecodedMessage]] = None
    wine_selections: Optional[List[DecodedMessage]] = None
    catering: Optional[bool] = False
    childrens_menu: Optional[bool] = False
    delivery: Optional[bool] = False
    dress_code: Optional[str] = None
    reservation_required: Optional[bool] = False
    takeout: Optional[bool] = False
    category: Optional[Ref] = None

    indexer = ContentIndexer(partition="partition_id")


@dataclass
class TransitAttribute:
    """Transit Details."""

    partition_id: Partition
    value: DecodedMessage

    indexer = ContentIndexer(partition="partition_id")


@dataclass
class VehicleServicesAttribute:
    """Vehicle Service Details."""

    partition_id: Partition
    value: DecodedMessage

    indexer = ContentIndexer(partition="partition_id")


@dataclass
class PostalCode(Name):
    """Postal Code Details."""

    pass


@dataclass
class Address:
    """Address Details."""

    partition_id: Partition
    postal_codes: List[PostalCode]
    location_address_type: str
    source_type: str
    cities: Optional[List[DecodedMessage]] = None
    states: Optional[List[DecodedMessage]] = None
    counties: Optional[List[DecodedMessage]] = None
    regions: Optional[List[DecodedMessage]] = None
    districts: Optional[List[DecodedMessage]] = None
    areas: Optional[List[DecodedMessage]] = None
    streets: Optional[List[DecodedMessage]] = None
    houses: Optional[List[DecodedMessage]] = None
    buildings: Optional[List[DecodedMessage]] = None
    building_units: Optional[List[DecodedMessage]] = None
    level_names: Optional[List[DecodedMessage]] = None
    unit_names: Optional[List[DecodedMessage]] = None
    postal_mappings: Optional[List[DecodedMessage]] = None
    state_codes: Optional[List[DecodedMessage]] = None
    country_code: Optional[int] = None
    category: Optional[Ref] = None

    indexer = ContentIndexer(partition="partition_id")


@dataclass
class Location:
    """Location Details."""

    partition_id: Partition
    location_id: Identifier
    location_type: str
    display_position: Point
    address: Address
    address_relation: str
    area_type: str
    segment_anchor: DecodedMessage
    segment_anchor_side: str

    geometry: Optional[MultiPolygon] = None
    level_info: Optional[DecodedMessage] = None
    accessors: Optional[DecodedMessage] = None
    political_geometry: Optional[DecodedMessage] = None
    alternate_geometry: Optional[DecodedMessage] = None
    within_location_ref: Optional[DecodedMessage] = None
    bounding_box: Optional[DecodedMessage] = None

    indexer = ContentIndexer(partition="partition_id", identifier="location_id")


@dataclass
class TruckAttribute:
    """Truck Attribute Details."""

    partition_id: Partition
    places: List[Place]
    high_canopy: Optional[bool] = False
    idle_reduction_system: Optional[bool] = False
    number_of_showers: Optional[str] = None
    showers: Optional[bool] = False
    truck_parking: Optional[bool] = False
    truck_scales: Optional[bool] = False
    truck_service: Optional[bool] = False
    truck_wash: Optional[bool] = False
    truck_secure_parking: Optional[bool] = False
    truck_night_parking_only: Optional[bool] = False
    truck_stop: Optional[bool] = False
    category: Optional[Ref] = None

    indexer = ContentIndexer(partition="partition_id")


@dataclass
class FuelTypeAttribute:
    """Fuel Type Details."""

    partition_id: Partition
    places: List[Place]
    biodiesel: Optional[bool] = False
    biodiesel_grade: Optional[str] = None
    cng: Optional[bool] = False
    diesel: Optional[bool] = False
    diesel_additive: Optional[str] = None
    diesel_additive_type: Optional[str] = None
    diesel_with_additives: Optional[bool] = False
    e85: Optional[bool] = False
    e10: Optional[bool] = False
    ethanol: Optional[bool] = False
    ethanol_with_additives: Optional[bool] = False
    gasoline: Optional[bool] = False
    high_volume_pumps: Optional[bool] = False
    hydrogen: Optional[bool] = False
    hydrogen_pressure: Optional[str] = None
    lpg: Optional[bool] = False
    midgrade: Optional[bool] = False
    pay_at_pump: Optional[bool] = False
    premium: Optional[bool] = False
    premium_with_additives: Optional[bool] = False
    regular: Optional[bool] = False
    regular_with_additives: Optional[bool] = False
    lng: Optional[bool] = False
    category: Optional[Ref] = None

    indexer = ContentIndexer(partition="partition_id")


@dataclass
class SocialSignal:
    """Social Signal Details."""

    partition_id: Partition
    value: DecodedMessage

    indexer = ContentIndexer(partition="partition_id")


@dataclass
class PortAttribute:
    """Port Details Details."""

    partition_id: Partition
    value: DecodedMessage

    indexer = ContentIndexer(partition="partition_id")


@dataclass
class SafetyCamera:
    """Safety Camera Details."""

    partition_id: Partition
    value: DecodedMessage

    indexer = ContentIndexer(partition="partition_id")


@dataclass
class BlackSpot:
    """Black Spot Details."""

    partition_id: Partition
    value: DecodedMessage

    indexer = ContentIndexer(partition="partition_id")


@dataclass
class MatchLevelAttribute:
    """Match Level Attribute Details."""

    partition_id: Partition
    places: List[Place]
    match_level: str

    indexer = ContentIndexer(partition="partition_id")


@dataclass
class AffiliationAttribute:
    """Affiliation Details."""

    partition_id: Partition
    value: DecodedMessage

    indexer = ContentIndexer(partition="partition_id")


@dataclass
class OfficeTypeAttribute:
    """Office Type Details."""

    partition_id: Partition
    value: DecodedMessage

    indexer = ContentIndexer(partition="partition_id")


@dataclass
class NoteTypeAttribute:
    """Note Type Details."""

    partition_id: Partition
    value: DecodedMessage

    indexer = ContentIndexer(partition="partition_id")


@dataclass
class PlaceCategoryConfidenceAttribute:
    """Place Category Confidence Details."""

    partition_id: Partition
    value: DecodedMessage

    indexer = ContentIndexer(partition="partition_id")


@dataclass
class PopularityAttribute:
    """Popularity Details."""

    partition_id: Partition
    value: DecodedMessage

    indexer = ContentIndexer(partition="partition_id")


@dataclass
class VendorUrlAttribute:
    """Vendor Url Details."""

    partition_id: Partition
    value: DecodedMessage

    indexer = ContentIndexer(partition="partition_id")
