from surveytools.coordinate import Coordinate
from surveytools.angle import Angle


class Measurement(object):

    # -----------------------
    # Serialisierung
    # -----------------------
    def to_dict(self) -> dict:
        """
        Konvertiere Measurement in JSON-freundliches dict.
        Winkel werden in gon gespeichert. measure_time wird 1:1 als String übernommen.
        """
        return {
            "target_number": self.target_number,
            "direction_gon": self.direction.get_gon(),
            "zenith_gon": self.zenith.get_gon(),
            "slope_distances": self.slope_distances,
            "atmospheric_data": self.atmospheric_data,
            "measure_time": self.measure_time,   # bleibt String
        }

    @classmethod
    def from_dict(cls, d: dict) -> "Measurement":
        """
        Erzeuge Measurement aus dict (reverse von to_dict).
        Erwartet: measure_time als String (oder None).
        """
        direction = Angle.from_gon(d["direction_gon"])
        zenith = Angle.from_gon(d["zenith_gon"])
        return cls(
            d["target_number"],
            direction,
            zenith,
            d["slope_distances"],
            d.get("atmospheric_data"),
            d.get("measure_time")    # String bleibt String
        )

    def __init__(self, target : str, direction: Angle, zenith: Angle, sd : float, atmospheric_data, measure_time):
        self.target_number = target
        self.direction = direction
        self.zenith = zenith
        self.slope_distances = sd
        self.atmospheric_data = atmospheric_data
        self.measure_time = measure_time

    def __str__(self):
        return "[target: " + str(self.target_number) + ", direction: " + str(self.direction) + " , zenith: " \
               + str(self.zenith) + ", slope_distances: " + str(self.slope_distances) + ", atmospheric_data: "\
               + str(self.atmospheric_data) + ", Measure Time: " + str(self.measure_time) + "]"

    def get_horizontal_distances(self):
        return self.slope_distances * self.zenith.sin()

    def get_delta_height(self):
        return self.slope_distances * self.zenith.cos()

    def get_local_coordinate(self):
        hd = self.get_horizontal_distances()
        y = hd * self.direction.sin()
        x = hd * self.direction.cos()
        z = self.get_delta_height()
        return Coordinate(self.target_number, x, y, z)

    def get_arra(self):
        return [self.target_number, self.direction.get_gon(), self.zenith.get_gon(), self.slope_distances ]