# Copyright 2021-2024 Teemu Ikonen
# SPDX-License-Identifier: GPL-3.0-only

import os
from datetime import timedelta

import gpxpy


class GpxSaver:

    def __init__(self, filename):
        os.makedirs(os.path.dirname(filename), exist_ok=True)
        self.autosave_interval = 60
        self.filename = filename
        self.counter = self.autosave_interval - 5

        self.gpx = gpxpy.gpx.GPX()
        track = gpxpy.gpx.GPXTrack()
        self.segment = gpxpy.gpx.GPXTrackSegment()
        track.segments.append(self.segment)
        self.gpx.tracks.append(track)

        self._length = 0.0
        self._last_length_ind = 0

        self.write()  # Try to write an empty file

    def write(self):
        with open(self.filename, 'w') as fp:
            fp.write(self.gpx.to_xml('1.0'))  # v1.0 has speed-tag

    def update(self, data):
        latlon = data.get("latlon")
        if latlon is None:
            return

        # mode2gpxmode = {
        #     "2": "2d",
        #     "3": "3d",
        #     None: "none",
        # }
        self.segment.points.append(gpxpy.gpx.GPXTrackPoint(
            latlon[0], latlon[1],
            elevation=data.get("altitude"),
            time=data.get("datetime"),
            # satellites=data.get("actives"),
            # type_of_gpx_fix=mode2gpxmode.get(data.get("mode"), "none"),
            speed=data.get("speed"),
            horizontal_dilution=data.get("hdop"),
            vertical_dilution=data.get("vdop"),
            position_dilution=data.get("pdop")))
        self.counter += 1
        if self.counter > self.autosave_interval:
            self.write()
            self.counter = 0

    def get_duration(self):
        return (self.segment.points[-1].time - self.segment.points[0].time
                if len(self.segment.points) > 0 else timedelta())

    def get_length(self):
        last_ind = len(self.segment.points) - 1
        if self._last_length_ind < last_ind:
            self._length += gpxpy.geo.length_2d(
                self.segment.points[self._last_length_ind:last_ind + 1])
            self._last_length_ind = last_ind
        return self._length
