from __future__ import annotations
from typing import Protocol, runtime_checkable, Sequence, Any, Tuple
from zempy.zosapi.editors.lde.enums.surface_column import SurfaceColumn

from zempy.zosapi.editors.lde.protocols.ilde_row import ILDERow
from zempy.zosapi.analysis.protocols.i_message import IMessage
from zempy.zosapi.editors.lde.enums.conversion_order import ConversionOrder
from zempy.zosapi.editors.lde.enums.pupil_apodization_type import PupilApodizationType
from zempy.zosapi.editors.lde.enums.point_cloud_file_format import PointCloudFileFormat
from zempy.zosapi.systemdata.enums.zemax_aperture_type import ZemaxApertureType
from zempy.zosapi.editors.lde.enums.tilt_type import TiltType

@runtime_checkable
class ILDETool_AddCoatingsToAllSurfaces(Protocol):
    ...

@runtime_checkable
class ILDETool_TiltDecenterElements(Protocol):
    ...

class CoordinateConversionResult:
    ...

@runtime_checkable
class ILensDataEditor(Protocol):
    # --- Methods returning rows/tools/messages ---
    def GetSurfaceAt(self, SurfaceNumber: int) -> ILDERow: ...
    def InsertNewSurfaceAt(self, SurfaceNumber: int) -> ILDERow: ...
    def AddSurface(self) -> ILDERow: ...
    def RemoveSurfaceAt(self, SurfaceNumber: int) -> bool: ...
    def RemoveSurfacesAt(self, SurfaceNumber: int, numSurfaces: int) -> int: ...
    def ShowLDE(self) -> bool: ...
    def HideLDE(self) -> None: ...
    def GetTool_AddCoatingsToAllSurfaces(self) -> ILDETool_AddCoatingsToAllSurfaces: ...
    def RunTool_AddCoatingsToAllSurfaces(self, settings: ILDETool_AddCoatingsToAllSurfaces) -> None: ...
    def RunTool_RemoveAllApertures(self) -> None: ...
    def RunTool_ConvertSemiDiametersToCircularApertures(self) -> None: ...
    def RunTool_ConvertSemiDiametersToFloatingApertures(self) -> None: ...
    def RunTool_ConvertSemiDiametersToMaximumApertures(self) -> None: ...
    def RunTool_ReplaceVignettingWithApertures(self) -> None: ...
    def RunTool_ConvertGlobalToLocalCoordinates(self, FirstSurface: int, LastSurface: int, order: ConversionOrder) -> CoordinateConversionResult: ...
    def RunTool_ConvertLocalToGlobalCoordinates(self, FirstSurface: int, LastSurface: int, referenceSurface: int) -> CoordinateConversionResult: ...
    def GetApodization(self, px: float, py: float) -> float: ...
    def GetFirstOrderData(self) -> Tuple[float, float, float, float, float]: ...
    def GetGlass(self, Surface: int) -> Tuple[bool, str, float, float, float]: ...
    def GetGlobalMatrix(self, Surface: int) -> Tuple[bool, float, float, float, float, float, float, float, float, float, float, float]: ...
    def GetIndex(self, Surface: int, NumberOfWavelengths: int, indexAtWavelength: Sequence[float]) -> int: ...
    def SetLabel(self, Surface: int, label: int) -> bool: ...
    def GetLabel(self, Surface: int) -> Tuple[bool, int]: ...
    def FindLabel(self, label: int) -> Tuple[bool, int]: ...
    def GetPupil(self) -> Tuple[ZemaxApertureType, float, float, float, float, float, PupilApodizationType, float]: ...
    def GetSag(self, Surface: int, X: float, Y: float) -> Tuple[bool, float, float]: ...
    def CopySurfaces(self, fromSurfaceNumber: int, NumberOfSurfaces: int, toSurfaceNumber: int) -> int: ...
    def CopySurfacesFrom(self, fromEditor: ILensDataEditor, fromSurfaceNumber: int, NumberOfSurfaces: int, toSurfaceNumber: int) -> int: ...
    def RunTool_ReverseElements(self, firstSurface: int, lastSurface: int) -> IMessage: ...
    def RunTool_AddFoldMirror(self, Surface: int, tilt: TiltType, reflectAngle: float) -> IMessage: ...
    def RunTool_DeleteFoldMirror(self, foldSurface: int) -> IMessage: ...
    def RunTool_MakeDoublePass(self, reflectAtSurface: int) -> IMessage: ...
    def RunTool_MakeFocal(self, focalLength: float) -> IMessage: ...
    def CanConvertSurfaceToFreeform(self, fromSurface: int) -> bool: ...
    def RunTool_ConvertSurfaceToFreeform(self, fromSurface: int, freeformSurface: int, gridNx: int, gridNy: int, limitToClearAperture: bool) -> IMessage: ...
    def RunTool_ConvertSurfaceInPlaceToFreeform(self, fromSurface: int, gridNx: int, gridNy: int, limitToClearAperture: bool) -> IMessage: ...
    def CanExportPointCloud(self, Surface: int) -> bool: ...
    def RunTool_ExportPointCloudFile(self, Surface: int, filename: str, gridNx: int, gridNy: int, includeSurfaceNormals: bool, format: PointCloudFileFormat) -> IMessage: ...
    def GetClosestGlass(self, Surface: int) -> str: ...
    def GetId(self, surface: int) -> int: ...
    def GetTool_TiltDecenterElements(self) -> ILDETool_TiltDecenterElements: ...
    def RunTool_TiltDecenterElements(self, settings: ILDETool_TiltDecenterElements) -> IMessage: ...

    # --- Properties ---
    @property
    def RowToSurfaceOffset(self) -> int: ...
    @property
    def NumberOfSurfaces(self) -> int: ...
    @property
    def NumberOfNonSequentialSurfaces(self) -> int: ...
    @property
    def FirstColumn(self) -> SurfaceColumn: ...
    @property
    def LastColumn(self) -> SurfaceColumn: ...
    @property
    def StopSurface(self) -> int: ...
