import inspect
from typing import Any

__author__ = "CAM"


def timeit(method):
    def timed(*args, **kw):
        import time

        ts = time.time()
        result = method(*args, **kw)
        te = time.time()

        print("%r (%r, %r) %2.9f saniye" % (method.__name__, args, kw, te - ts))
        print(inspect.currentframe().f_back.f_code)
        return result

    return timed


class XYZO(object):
    def __init__(self, X=[0, 0, 0], Y=[0, 0, 0], Z=[0, 0, 0], O=[0, 0, 0]):
        # --->Sabit Degiskenler
        self.__X = X
        self.__Y = Y
        self.__Z = Z
        self.__O = O

    @property
    def X(self):
        return self.__X

    @X.setter
    def X(self, dgr):
        self.__X = dgr

    @property
    def Y(self):
        return self.__Y

    @Y.setter
    def Y(self, dgr):
        self.__Y = dgr

    @property
    def Z(self):
        return self.__Z

    @Z.setter
    def Z(self, dgr):
        self.__Z = dgr

    @property
    def O(self):
        return self.__O

    @O.setter
    def O(self, dgr):
        self.__O = dgr

    def __call__(self):
        return [self.X, self.Y, self.Z, self.O]

    def __str__(self):
        return repr([self.X, self.Y, self.Z, self.O])

    def to_dict(self):
        return {
            "x": self.X.to_dict(),
            "y": self.Y.to_dict(),
            "z": self.Z.to_dict(),
            "o": self.O.to_dict(),
        }


class XYZ(object):
    def __init__(self, X: float = 0, Y: float = 0, Z: float = 0,sahip=None):
        # --->Sabit Degiskenler
        self.__X = X
        self.__Y = Y
        self.__Z = Z

    @property
    def X(self):
        return self.__X

    @X.setter
    def X(self, dgr):
        self.__X = dgr

    @property
    def Y(self):
        return self.__Y

    @Y.setter
    def Y(self, dgr):
        self.__Y = dgr

    @property
    def Z(self):
        return self.__Z

    @Z.setter
    def Z(self, dgr):
        self.__Z = dgr

    def __call__(self):
        return [self.X, self.Y, self.Z]

    def __str__(self):
        return repr([self.X, self.Y, self.Z])

    def to_dict(self):
        return {"x": self.X, "y": self.Y, "z": self.Z}

    def to_array(self):
        return [self.X, self.Y, self.Z]


class IJK(object):
    def __init__(self, I: float = 0, J: float = 0, K: float = 0):
        # --->Sabit Degiskenler
        self.__I = I
        self.__J = J
        self.__K = K

    @property
    def I(self):
        return self.__I

    @I.setter
    def I(self, dgr):
        self.__I = dgr

    @property
    def J(self):
        return self.__J

    @J.setter
    def J(self, dgr):
        self.__J = dgr

    @property
    def K(self):
        return self.__K

    @K.setter
    def K(self, dgr):
        self.__K = dgr

    def __call__(self):
        return [self.I, self.J, self.K]

    def __str__(self):
        return repr([self.I, self.J, self.K])

    def to_dict(self):
        return {"i": self.I, "j": self.J, "k": self.K}


class SifirKonum(object):
    def __init__(
        self,
        Xmin: float = 0.0,
        Xmax: float = 0.0,
        Ymin: float = 0.0,
        Ymax: float = 0.0,
        Zmin: float = 0.0,
        Zmax: float = 0.0,
    ):
        # --->Sabit Degiskenler
        self.__Xmin = Xmin
        self.__Xmax = Xmax
        self.__Ymin = Ymin
        self.__Ymax = Ymax
        self.__Zmin = Zmin
        self.__Zmax = Zmax

    @property
    def Xmin(self):
        return self.__Xmin

    @Xmin.setter
    def Xmin(self, value):
        self.__Xmin = value

    @property
    def Xmax(self):
        return self.__Xmax

    @Xmax.setter
    def Xmax(self, value):
        self.__Xmax = value

    @property
    def Ymin(self):
        return self.__Ymin

    @Ymin.setter
    def Ymin(self, value):
        self.__Ymin = value

    @property
    def Ymax(self):
        return self.__Ymax

    @Ymax.setter
    def Ymax(self, value):
        self.__Ymax = value

    @property
    def Zmin(self):
        return self.__Zmin

    @Zmin.setter
    def Zmin(self, value):
        self.__Zmin = value

    @property
    def Zmax(self):
        return self.__Zmax

    @Zmax.setter
    def Zmax(self, value):
        self.__Zmax = value

    @property
    def miX0Merkez(self) -> bool:
        return round(self.Xmin, 3) == round(self.Xmax, 3)

    @property
    def miX0XEksiDuvar(self) -> bool:
        return round(self.Xmin, 3) == 0.0

    @property
    def miX0XArtiDuvar(self) -> bool:
        return round(self.Xmax, 3) == 0.0

    @property
    def miY0Merkez(self) -> bool:
        return round(self.Ymin, 3) == round(self.Ymax, 3)

    @property
    def miY0YEksiDuvar(self) -> bool:
        return round(self.Ymin, 3) == 0.0

    @property
    def miY0YArtiDuvar(self) -> bool:
        return round(self.Ymax, 3) == 0.0

    @property
    def miZ0Merkez(self) -> bool:
        return round(self.Zmin, 3) == round(self.Zmax, 3)

    @property
    def miZ0Taban(self) -> bool:
        return round(self.Zmin, 3) == 0.0

    @property
    def miZ0Ustu(self) -> bool:
        return round(self.Zmax, 3) == 0.0

    @property
    def XOlcusu(self):
        return self.__Xmin + self.__Xmax

    @property
    def YOlcusu(self):
        return self.__Ymin + self.__Ymax

    @property
    def ZOlcusu(self):
        return self.__Zmin + self.__Zmax

    @property
    def X_Sifir(self) -> str:
        __rslt: Any = None

        if self.miX0Merkez:
            __rslt = f"Merkez ( X±={round(self.Xmin, 3)}mm )"
        elif self.miX0XEksiDuvar:
            __rslt = "Sol Duvar (X Eksi)"
        elif self.miX0XArtiDuvar:
            __rslt = "Sağ Duvar (X Artı)"
        else:
            __rslt = f"X Eksi Uç Nokta = {round(self.Xmin,3)}mm <-> X Artı Uç Nokta = {round(self.Xmax,3)}mm"

        return __rslt

    @property
    def Y_Sifir(self) -> str:
        __rslt: Any = None

        if self.miY0Merkez:
            __rslt = f"Merkez ( Y±={round(self.Ymin, 3)}mm )"
        elif self.miY0YEksiDuvar:
            __rslt = "Ön Duvar (Y Eksi)"
        elif self.miY0YArtiDuvar:
            __rslt = "Arka Duvar (Y Artı)"
        else:
            __rslt = f"Y Eksi Uç Nokta = {round(self.Ymin,3)}mm <-> Y Artı Uç Nokta = {round(self.Ymax,3)}mm"

        return __rslt

    @property
    def Z_Sifir(self) -> str:
        __rslt: Any = None

        if self.miZ0Merkez:
            __rslt = "Merkez"
        elif self.miZ0Taban:
            __rslt = f"Taban (Üstü Z{round(self.Zmax,3)}mm)"
        elif self.miZ0Ustu:
            __rslt = f"Üstü (Taban Z{round(self.Zmin,3)*-1}mm)"
        else:
            __rslt = f"Taban Z{round(self.Zmin,3)*-1}mm <-> Parça Üstü Z{round(self.Zmax,3)}mm"

        return __rslt

    @property
    def toStr(self):
        return f"X0={self.X_Sifir} Y0={self.Y_Sifir} Z0={self.Z_Sifir}"

    def __call__(self):
        return [self.Xmin, self.Xmax, self.Ymin, self.Ymax, self.Zmin, self.Zmax]

    def __str__(self):
        return repr({"X": self.X_Sifir, "Y": self.Y_Sifir, "Z": self.Z_Sifir})
