import asyncio
import logging
import random
from abc import abstractmethod

import gpxpy


class LocationSimulationBase:
    def __init__(self):
        self.logger = logging.getLogger(self.__class__.__name__)

    @abstractmethod
    async def set(self, latitude: float, longitude: float) -> None:
        pass

    @abstractmethod
    async def clear(self) -> None:
        pass

    async def play_gpx_file(self, filename: str, disable_sleep: bool = False, timing_randomness_range: int = 0):
        with open(filename) as f:
            gpx = gpxpy.parse(f)

        last_time = None
        gpx_timing_noise = None
        for track in gpx.tracks:
            for segment in track.segments:
                for point in segment.points:
                    if last_time is not None:
                        duration = (point.time - last_time).total_seconds()
                        if duration >= 0 and not disable_sleep:
                            if timing_randomness_range:
                                gpx_timing_noise = (
                                    random.randint(-timing_randomness_range, timing_randomness_range) / 1000
                                )
                                duration += gpx_timing_noise

                            self.logger.info(f"waiting for {duration:.3f}s")
                            await asyncio.sleep(duration)
                    last_time = point.time
                    self.logger.info(f"set location to {point.latitude} {point.longitude}")
                    await self.set(point.latitude, point.longitude)
