from abc import ABC, abstractmethod
import numpy as np

from models.core import GPSPoint
from models.satellite import TileBounds


class CoordinateTransformerBase(ABC):
    @abstractmethod
    def gps_to_local(
        self, gps: GPSPoint, origin: GPSPoint
    ) -> tuple[float, float]:
        pass

    @abstractmethod
    def local_to_gps(
        self, local: tuple[float, float], origin: GPSPoint
    ) -> GPSPoint:
        pass

    @abstractmethod
    def pixel_to_gps(
        self,
        pixel: tuple[float, float],
        homography: np.ndarray,
        tile_bounds: TileBounds,
    ) -> GPSPoint:
        pass

    @abstractmethod
    def gps_to_pixel(
        self,
        gps: GPSPoint,
        homography: np.ndarray,
        tile_bounds: TileBounds,
    ) -> tuple[float, float]:
        pass

    @abstractmethod
    def compute_distance_meters(
        self, gps1: GPSPoint, gps2: GPSPoint
    ) -> float:
        pass

    @abstractmethod
    def compute_bearing(
        self, from_gps: GPSPoint, to_gps: GPSPoint
    ) -> float:
        pass

    @abstractmethod
    def offset_gps(
        self, gps: GPSPoint, distance_m: float, bearing_deg: float
    ) -> GPSPoint:
        pass

