"""Module for finding public toilets around given coordinates."""
import logging
import xml.etree.ElementTree as ET

from ..overpass.overpass import Overpass, get_base_info
from ..structs.landmark import Toilets
from ..constants import OSM_CACHE_DIR


# silence the overpass logger
logging.getLogger('Overpass').setLevel(level=logging.CRITICAL)

class ToiletsManager:
    """
    Manages the process of fetching and caching toilet information from 
    OpenStreetMap (OSM) based on a specified location and radius.

    This class is responsible for:
    - Fetching toilet data from OSM using Overpass API around a given set of 
      coordinates (latitude, longitude).
    - Using a caching strategy to optimize requests by saving and retrieving 
      data from a local cache.
    - Logging important events and errors related to data fetching.

    Attributes:
        logger (logging.Logger): Logger for the class to capture events.
        location (tuple[float, float]): Latitude and longitude representing the 
            location to search around.
        radius (int): The search radius in meters for finding nearby toilets.
        overpass (Overpass): The Overpass API instance used to query OSM.
    """
    logger = logging.getLogger(__name__)

    location: tuple[float, float]
    radius: int    # radius in meters


    def __init__(self, location: tuple[float, float], radius : int) -> None:

        self.radius = radius
        self.location = location

        # Setup the caching in the Overpass class.
        self.overpass = Overpass(caching_strategy='XML', cache_dir=OSM_CACHE_DIR)


    def generate_toilet_list(self) -> list[Toilets] :
        """
        Generates a list of toilet locations by fetching data from OpenStreetMap (OSM) 
        around the given coordinates stored in `self.location`.

        Returns:
        list[Toilets]: A list of `Toilets` objects containing detailed information 
                       about the toilets found around the given coordinates.
        """
        bbox = tuple((self.radius, self.location[0], self.location[1]))
        osm_types = ['node', 'way', 'relation']
        toilets_list = []

        query = self.overpass.build_query(
                area = bbox,
                osm_types = osm_types,
                selector = '"amenity"="toilets"',
                out = 'ids center tags'
                )
        self.logger.debug(f"Query: {query}")

        try:
            result = self.overpass.send_query(query)
        except Exception as e:
            self.logger.error(f"Error fetching landmarks: {e}")
            return None

        toilets_list = self.xml_to_toilets(result)

        return toilets_list


    def xml_to_toilets(self, root: ET.Element) -> list[Toilets]:
        """
        Parse the Overpass API result and extract landmarks.

        This method processes the XML root element returned by the Overpass API and 
        extracts landmarks of types 'node', 'way', and 'relation'. It retrieves 
        relevant information such as name, coordinates, and tags, and converts them 
        into Landmark objects.

        Args:
        root (ET.Element): The root element of the XML response from Overpass API.
        elem_type (str): The type of landmark (e.g., node, way, relation).

        Returns:
        list[Landmark]: A list of Landmark objects extracted from the XML data.
        """
        if root is None :
            return []

        toilets_list = []
        for osm_type in ['node', 'way', 'relation'] :
            for elem in root.findall(osm_type):
                # Get coordinates and append them to the points list
                _, coords = get_base_info(elem, osm_type)
                if coords is None :
                    continue

                toilets = Toilets(location=coords)

                # Extract tags as a dictionary
                tags = {tag.get('k'): tag.get('v') for tag in elem.findall('tag')}

                if 'wheelchair' in tags.keys() and tags['wheelchair'] == 'yes':
                    toilets.wheelchair = True

                if 'changing_table' in tags.keys() and tags['changing_table'] == 'yes':
                    toilets.changing_table = True

                if 'fee' in tags.keys() and tags['fee'] == 'yes':
                    toilets.fee = True

                if 'opening_hours' in tags.keys() :
                    toilets.opening_hours = tags['opening_hours']

                toilets_list.append(toilets)

        return toilets_list