# This file is generated by autd_wrapper_generator (https://github.com/shinolab/autd-wrapper-generator)

import threading
import ctypes
import os
from ctypes import c_void_p, c_bool, c_int, POINTER, c_double, c_char_p, c_ubyte, c_uint, c_ulong, c_ushort


class Singleton(type):
    _instances = {}
    _lock = threading.Lock()

    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            with cls._lock:
                if cls not in cls._instances:
                    cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
        return cls._instances[cls]


class Nativemethods(metaclass=Singleton):
    def init_dll(self, bin_location, bin_prefix, bin_ext):
        self._bin_location = bin_location
        self._bin_prefix = bin_prefix
        self._bin_ext = bin_ext

    def init_autd3capi(self):
        if hasattr(self, 'autd3capi'):
            return
        self.autd3capi = ctypes.CDLL(os.path.join(self._bin_location, self._bin_prefix + "autd3capi_1.4.0" + self._bin_ext))
        self.autd3capi.AUTDCreateController.argtypes = [POINTER(c_void_p)]
        self.autd3capi.AUTDCreateController.restypes = [None]

        self.autd3capi.AUTDOpenController.argtypes = [c_void_p, c_void_p]
        self.autd3capi.AUTDOpenController.restypes = [c_bool]

        self.autd3capi.AUTDAddDevice.argtypes = [c_void_p, c_double, c_double, c_double, c_double, c_double, c_double, c_int]
        self.autd3capi.AUTDAddDevice.restypes = [c_int]

        self.autd3capi.AUTDAddDeviceQuaternion.argtypes = [c_void_p, c_double, c_double, c_double, c_double, c_double, c_double, c_double, c_int]
        self.autd3capi.AUTDAddDeviceQuaternion.restypes = [c_int]

        self.autd3capi.AUTDDeleteDevice.argtypes = [c_void_p, c_int]
        self.autd3capi.AUTDDeleteDevice.restypes = [c_int]

        self.autd3capi.AUTDClearDevices.argtypes = [c_void_p]
        self.autd3capi.AUTDClearDevices.restypes = [None]

        self.autd3capi.AUTDCloseController.argtypes = [c_void_p]
        self.autd3capi.AUTDCloseController.restypes = [c_bool]

        self.autd3capi.AUTDClear.argtypes = [c_void_p]
        self.autd3capi.AUTDClear.restypes = [c_bool]

        self.autd3capi.AUTDFreeController.argtypes = [c_void_p]
        self.autd3capi.AUTDFreeController.restypes = [None]

        self.autd3capi.AUTDIsOpen.argtypes = [c_void_p]
        self.autd3capi.AUTDIsOpen.restypes = [c_bool]

        self.autd3capi.AUTDIsSilentMode.argtypes = [c_void_p]
        self.autd3capi.AUTDIsSilentMode.restypes = [c_bool]

        self.autd3capi.AUTDIsForceFan.argtypes = [c_void_p]
        self.autd3capi.AUTDIsForceFan.restypes = [c_bool]

        self.autd3capi.AUTDIsReadsFPGAInfo.argtypes = [c_void_p]
        self.autd3capi.AUTDIsReadsFPGAInfo.restypes = [c_bool]

        self.autd3capi.AUTDSetSilentMode.argtypes = [c_void_p, c_bool]
        self.autd3capi.AUTDSetSilentMode.restypes = [None]

        self.autd3capi.AUTDSetReadsFPGAInfo.argtypes = [c_void_p, c_bool]
        self.autd3capi.AUTDSetReadsFPGAInfo.restypes = [None]

        self.autd3capi.AUTDSetForceFan.argtypes = [c_void_p, c_bool]
        self.autd3capi.AUTDSetForceFan.restypes = [None]

        self.autd3capi.AUTDGetWavelength.argtypes = [c_void_p]
        self.autd3capi.AUTDGetWavelength.restypes = [c_double]

        self.autd3capi.AUTDGetAttenuation.argtypes = [c_void_p]
        self.autd3capi.AUTDGetAttenuation.restypes = [c_double]

        self.autd3capi.AUTDSetWavelength.argtypes = [c_void_p, c_double]
        self.autd3capi.AUTDSetWavelength.restypes = [None]

        self.autd3capi.AUTDSetAttenuation.argtypes = [c_void_p, c_double]
        self.autd3capi.AUTDSetAttenuation.restypes = [None]

        self.autd3capi.AUTDGetFPGAInfo.argtypes = [c_void_p, POINTER(c_ubyte)]
        self.autd3capi.AUTDGetFPGAInfo.restypes = [c_bool]

        self.autd3capi.AUTDUpdateCtrlFlags.argtypes = [c_void_p]
        self.autd3capi.AUTDUpdateCtrlFlags.restypes = [c_bool]

        self.autd3capi.AUTDSetOutputDelay.argtypes = [c_void_p, POINTER(c_ubyte)]
        self.autd3capi.AUTDSetOutputDelay.restypes = [c_bool]

        self.autd3capi.AUTDSetEnable.argtypes = [c_void_p, POINTER(c_ubyte)]
        self.autd3capi.AUTDSetEnable.restypes = [c_bool]

        self.autd3capi.AUTDSetDelayEnable.argtypes = [c_void_p, POINTER(c_ushort)]
        self.autd3capi.AUTDSetDelayEnable.restypes = [c_bool]

        self.autd3capi.AUTDGetLastError.argtypes = [c_char_p]
        self.autd3capi.AUTDGetLastError.restypes = [c_int]

        self.autd3capi.AUTDNumDevices.argtypes = [c_void_p]
        self.autd3capi.AUTDNumDevices.restypes = [c_int]

        self.autd3capi.AUTDNumTransducers.argtypes = [c_void_p]
        self.autd3capi.AUTDNumTransducers.restypes = [c_int]

        self.autd3capi.AUTDDeviceIdxForTransIdx.argtypes = [c_void_p, c_int]
        self.autd3capi.AUTDDeviceIdxForTransIdx.restypes = [c_int]

        self.autd3capi.AUTDTransPositionByGlobal.argtypes = [c_void_p, c_int, POINTER(c_double), POINTER(c_double), POINTER(c_double)]
        self.autd3capi.AUTDTransPositionByGlobal.restypes = [None]

        self.autd3capi.AUTDTransPositionByLocal.argtypes = [c_void_p, c_int, c_int, POINTER(c_double), POINTER(c_double), POINTER(c_double)]
        self.autd3capi.AUTDTransPositionByLocal.restypes = [None]

        self.autd3capi.AUTDDeviceXDirection.argtypes = [c_void_p, c_int, POINTER(c_double), POINTER(c_double), POINTER(c_double)]
        self.autd3capi.AUTDDeviceXDirection.restypes = [None]

        self.autd3capi.AUTDDeviceYDirection.argtypes = [c_void_p, c_int, POINTER(c_double), POINTER(c_double), POINTER(c_double)]
        self.autd3capi.AUTDDeviceYDirection.restypes = [None]

        self.autd3capi.AUTDDeviceZDirection.argtypes = [c_void_p, c_int, POINTER(c_double), POINTER(c_double), POINTER(c_double)]
        self.autd3capi.AUTDDeviceZDirection.restypes = [None]

        self.autd3capi.AUTDGetFirmwareInfoListPointer.argtypes = [c_void_p, POINTER(c_void_p)]
        self.autd3capi.AUTDGetFirmwareInfoListPointer.restypes = [c_int]

        self.autd3capi.AUTDGetFirmwareInfo.argtypes = [c_void_p, c_int, c_char_p, c_char_p]
        self.autd3capi.AUTDGetFirmwareInfo.restypes = [None]

        self.autd3capi.AUTDFreeFirmwareInfoListPointer.argtypes = [c_void_p]
        self.autd3capi.AUTDFreeFirmwareInfoListPointer.restypes = [None]

        self.autd3capi.AUTDGainNull.argtypes = [POINTER(c_void_p)]
        self.autd3capi.AUTDGainNull.restypes = [None]

        self.autd3capi.AUTDGainGrouped.argtypes = [POINTER(c_void_p)]
        self.autd3capi.AUTDGainGrouped.restypes = [None]

        self.autd3capi.AUTDGainGroupedAdd.argtypes = [c_void_p, c_int, c_void_p]
        self.autd3capi.AUTDGainGroupedAdd.restypes = [None]

        self.autd3capi.AUTDGainFocalPoint.argtypes = [POINTER(c_void_p), c_double, c_double, c_double, c_ubyte]
        self.autd3capi.AUTDGainFocalPoint.restypes = [None]

        self.autd3capi.AUTDGainBesselBeam.argtypes = [
            POINTER(c_void_p),
            c_double,
            c_double,
            c_double,
            c_double,
            c_double,
            c_double,
            c_double,
            c_ubyte]
        self.autd3capi.AUTDGainBesselBeam.restypes = [None]

        self.autd3capi.AUTDGainPlaneWave.argtypes = [POINTER(c_void_p), c_double, c_double, c_double, c_ubyte]
        self.autd3capi.AUTDGainPlaneWave.restypes = [None]

        self.autd3capi.AUTDGainCustom.argtypes = [POINTER(c_void_p), POINTER(c_ushort), c_int]
        self.autd3capi.AUTDGainCustom.restypes = [None]

        self.autd3capi.AUTDGainTransducerTest.argtypes = [POINTER(c_void_p), c_int, c_ubyte, c_ubyte]
        self.autd3capi.AUTDGainTransducerTest.restypes = [None]

        self.autd3capi.AUTDDeleteGain.argtypes = [c_void_p]
        self.autd3capi.AUTDDeleteGain.restypes = [None]

        self.autd3capi.AUTDModulationStatic.argtypes = [POINTER(c_void_p), c_ubyte]
        self.autd3capi.AUTDModulationStatic.restypes = [None]

        self.autd3capi.AUTDModulationCustom.argtypes = [POINTER(c_void_p), POINTER(c_ubyte), c_uint]
        self.autd3capi.AUTDModulationCustom.restypes = [None]

        self.autd3capi.AUTDModulationSine.argtypes = [POINTER(c_void_p), c_int, c_double, c_double]
        self.autd3capi.AUTDModulationSine.restypes = [None]

        self.autd3capi.AUTDModulationSinePressure.argtypes = [POINTER(c_void_p), c_int, c_double, c_double]
        self.autd3capi.AUTDModulationSinePressure.restypes = [None]

        self.autd3capi.AUTDModulationSquare.argtypes = [POINTER(c_void_p), c_int, c_ubyte, c_ubyte]
        self.autd3capi.AUTDModulationSquare.restypes = [None]

        self.autd3capi.AUTDDeleteModulation.argtypes = [c_void_p]
        self.autd3capi.AUTDDeleteModulation.restypes = [None]

        self.autd3capi.AUTDSequence.argtypes = [POINTER(c_void_p)]
        self.autd3capi.AUTDSequence.restypes = [None]

        self.autd3capi.AUTDSequenceAddPoint.argtypes = [c_void_p, c_double, c_double, c_double]
        self.autd3capi.AUTDSequenceAddPoint.restypes = [c_bool]

        self.autd3capi.AUTDSequenceAddPoints.argtypes = [c_void_p, POINTER(c_double), c_ulong]
        self.autd3capi.AUTDSequenceAddPoints.restypes = [c_bool]

        self.autd3capi.AUTDSequenceSetFreq.argtypes = [c_void_p, c_double]
        self.autd3capi.AUTDSequenceSetFreq.restypes = [c_double]

        self.autd3capi.AUTDSequenceFreq.argtypes = [c_void_p]
        self.autd3capi.AUTDSequenceFreq.restypes = [c_double]

        self.autd3capi.AUTDSequencePeriod.argtypes = [c_void_p]
        self.autd3capi.AUTDSequencePeriod.restypes = [c_uint]

        self.autd3capi.AUTDSequenceSamplingPeriod.argtypes = [c_void_p]
        self.autd3capi.AUTDSequenceSamplingPeriod.restypes = [c_uint]

        self.autd3capi.AUTDSequenceSamplingFreq.argtypes = [c_void_p]
        self.autd3capi.AUTDSequenceSamplingFreq.restypes = [c_double]

        self.autd3capi.AUTDSequenceSamplingFreqDiv.argtypes = [c_void_p]
        self.autd3capi.AUTDSequenceSamplingFreqDiv.restypes = [c_ushort]

        self.autd3capi.AUTDDeleteSequence.argtypes = [c_void_p]
        self.autd3capi.AUTDDeleteSequence.restypes = [None]

        self.autd3capi.AUTDCircumSequence.argtypes = [
            POINTER(c_void_p),
            c_double,
            c_double,
            c_double,
            c_double,
            c_double,
            c_double,
            c_double,
            c_ulong]
        self.autd3capi.AUTDCircumSequence.restypes = [None]

        self.autd3capi.AUTDStop.argtypes = [c_void_p]
        self.autd3capi.AUTDStop.restypes = [c_bool]

        self.autd3capi.AUTDPause.argtypes = [c_void_p]
        self.autd3capi.AUTDPause.restypes = [c_bool]

        self.autd3capi.AUTDResume.argtypes = [c_void_p]
        self.autd3capi.AUTDResume.restypes = [c_bool]

        self.autd3capi.AUTDSendGain.argtypes = [c_void_p, c_void_p]
        self.autd3capi.AUTDSendGain.restypes = [c_bool]

        self.autd3capi.AUTDSendModulation.argtypes = [c_void_p, c_void_p]
        self.autd3capi.AUTDSendModulation.restypes = [c_bool]

        self.autd3capi.AUTDSendGainModulation.argtypes = [c_void_p, c_void_p, c_void_p]
        self.autd3capi.AUTDSendGainModulation.restypes = [c_bool]

        self.autd3capi.AUTDSendSequence.argtypes = [c_void_p, c_void_p]
        self.autd3capi.AUTDSendSequence.restypes = [c_bool]

        self.autd3capi.AUTDSTMController.argtypes = [POINTER(c_void_p), c_void_p]
        self.autd3capi.AUTDSTMController.restypes = [None]

        self.autd3capi.AUTDAddSTMGain.argtypes = [c_void_p, c_void_p]
        self.autd3capi.AUTDAddSTMGain.restypes = [c_bool]

        self.autd3capi.AUTDStartSTM.argtypes = [c_void_p, c_double]
        self.autd3capi.AUTDStartSTM.restypes = [c_bool]

        self.autd3capi.AUTDStopSTM.argtypes = [c_void_p]
        self.autd3capi.AUTDStopSTM.restypes = [c_bool]

        self.autd3capi.AUTDFinishSTM.argtypes = [c_void_p]
        self.autd3capi.AUTDFinishSTM.restypes = [c_bool]

    def init_autd3capi_holo_gain(self):
        if hasattr(self, 'autd3capi_holo_gain'):
            return
        self.autd3capi_holo_gain = ctypes.CDLL(os.path.join(self._bin_location, self._bin_prefix + "autd3capi_1.4.0-holo-gain" + self._bin_ext))
        self.autd3capi_holo_gain.AUTDEigen3Backend.argtypes = [POINTER(c_void_p)]
        self.autd3capi_holo_gain.AUTDEigen3Backend.restypes = [None]

        self.autd3capi_holo_gain.AUTDDeleteBackend.argtypes = [c_void_p]
        self.autd3capi_holo_gain.AUTDDeleteBackend.restypes = [None]

        self.autd3capi_holo_gain.AUTDGainHoloSDP.argtypes = [POINTER(c_void_p), c_void_p, POINTER(
            c_double), POINTER(c_double), c_int, c_double, c_double, c_ulong, c_bool]
        self.autd3capi_holo_gain.AUTDGainHoloSDP.restypes = [None]

        self.autd3capi_holo_gain.AUTDGainHoloEVD.argtypes = [
            POINTER(c_void_p), c_void_p, POINTER(c_double), POINTER(c_double), c_int, c_double, c_bool]
        self.autd3capi_holo_gain.AUTDGainHoloEVD.restypes = [None]

        self.autd3capi_holo_gain.AUTDGainHoloNaive.argtypes = [POINTER(c_void_p), c_void_p, POINTER(c_double), POINTER(c_double), c_int]
        self.autd3capi_holo_gain.AUTDGainHoloNaive.restypes = [None]

        self.autd3capi_holo_gain.AUTDGainHoloGS.argtypes = [POINTER(c_void_p), c_void_p, POINTER(c_double), POINTER(c_double), c_int, c_ulong]
        self.autd3capi_holo_gain.AUTDGainHoloGS.restypes = [None]

        self.autd3capi_holo_gain.AUTDGainHoloGSPAT.argtypes = [POINTER(c_void_p), c_void_p, POINTER(c_double), POINTER(c_double), c_int, c_ulong]
        self.autd3capi_holo_gain.AUTDGainHoloGSPAT.restypes = [None]

        self.autd3capi_holo_gain.AUTDGainHoloLM.argtypes = [POINTER(c_void_p), c_void_p, POINTER(
            c_double), POINTER(c_double), c_int, c_double, c_double, c_double, c_ulong, POINTER(c_double), c_int]
        self.autd3capi_holo_gain.AUTDGainHoloLM.restypes = [None]

        self.autd3capi_holo_gain.AUTDGainHoloGreedy.argtypes = [POINTER(c_void_p), POINTER(c_double), POINTER(c_double), c_int, c_int]
        self.autd3capi_holo_gain.AUTDGainHoloGreedy.restypes = [None]

    def init_autd3capi_soem_link(self):
        if hasattr(self, 'autd3capi_soem_link'):
            return
        self.autd3capi_soem_link = ctypes.CDLL(os.path.join(self._bin_location, self._bin_prefix + "autd3capi_1.4.0-soem-link" + self._bin_ext))
        self.autd3capi_soem_link.AUTDGetAdapterPointer.argtypes = [POINTER(c_void_p)]
        self.autd3capi_soem_link.AUTDGetAdapterPointer.restypes = [c_int]

        self.autd3capi_soem_link.AUTDGetAdapter.argtypes = [c_void_p, c_int, c_char_p, c_char_p]
        self.autd3capi_soem_link.AUTDGetAdapter.restypes = [None]

        self.autd3capi_soem_link.AUTDFreeAdapterPointer.argtypes = [c_void_p]
        self.autd3capi_soem_link.AUTDFreeAdapterPointer.restypes = [None]

        self.autd3capi_soem_link.AUTDLinkSOEM.argtypes = [POINTER(c_void_p), c_char_p, c_int, c_uint]
        self.autd3capi_soem_link.AUTDLinkSOEM.restypes = [None]

    def init_autd3capi_twincat_link(self):
        if hasattr(self, 'autd3capi_twincat_link'):
            return
        self.autd3capi_twincat_link = ctypes.CDLL(os.path.join(self._bin_location, self._bin_prefix + "autd3capi_1.4.0-twincat-link" + self._bin_ext))
        self.autd3capi_twincat_link.AUTDLinkTwinCAT.argtypes = [POINTER(c_void_p)]
        self.autd3capi_twincat_link.AUTDLinkTwinCAT.restypes = [None]
