﻿using System;
using System.Runtime.InteropServices;

namespace Aidlab
{
    public static class AidlabAPI
    {
        private const string LibraryName =
#if UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN
            "libaidlab_sdk.dll";
#elif UNITY_STANDALONE_OSX || UNITY_EDITOR_OSX
            "libaidlab_sdk.dylib";
#elif UNITY_IOS || UNITY_TVOS
            "__Internal";
#else
            "aidlab_sdk";
#endif

        public enum LogLevel : int
        {
            Debug = 0,
            Info = 1,
            Warn = 2,
            Error = 3,
        }

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate void callbackSampleTime(IntPtr context, ulong timestamp, float value);

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate void callbackActivity(IntPtr context, ulong timestamp, ActivityType activity);

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate void callbackRespirationRate(IntPtr context, ulong timestamp, uint value);

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate void callbackSteps(IntPtr context, ulong timestamp, ulong steps);

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate void callbackBatteryLevel(IntPtr context, byte stateOfCharge);

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate void callbackWearState(IntPtr context, WearState wearState);

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate void callbackAccelerometer(IntPtr context, ulong timestamp, float ax, float ay, float az);

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate void callbackGyroscope(IntPtr context, ulong timestamp, float gx, float gy, float gz);

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate void callbackMagnetometer(IntPtr context, ulong timestamp, float mx, float my, float mz);

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate void callbackOrientation(IntPtr context, ulong timestamp, float roll, float pitch, float yaw);

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate void callbackBodyPosition(IntPtr context, ulong timestamp, BodyPosition bodyPosition);

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate void callbackQuaternion(IntPtr context, ulong timestamp, float qw, float qx, float qy, float qz);

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate void callbackHeartRate(IntPtr context, ulong timestamp, int heartRate);

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate void callbackRr(IntPtr context, ulong timestamp, int rr);

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate void callbackSoundVolume(IntPtr context, ulong timestamp, ushort soundVolume);

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate void callbackPressure(IntPtr context, ulong timestamp, int pressure);

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate void callbackSignalQuality(IntPtr context, ulong timestamp, byte value);

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate void callbackUserEvent(IntPtr context, ulong timestamp);

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate void callbackExercise(IntPtr context, Exercise exercise);

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate void callbackSyncState(IntPtr context, SyncState syncState);

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate void callbackUnsynchronizedSize(IntPtr context, uint size, float progress);

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate void callbackBleSend(IntPtr context, IntPtr data, int size);

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate void callbackBleReady(IntPtr context);

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate void callbackPayload(IntPtr context, IntPtr process, IntPtr payload, UIntPtr payloadLength);

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate void callbackLogMessage(IntPtr context, LogLevel level, IntPtr message);

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate void callbackEda(IntPtr context, ulong timestamp, float conductance);

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate void callbackGps(
            IntPtr context,
            ulong timestamp,
            float lat,
            float lon,
            float alt,
            float speed,
            float heading,
            float hdop);

        [DllImport(LibraryName, EntryPoint = "AidlabSDK_create", CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr AidlabSDK_create(byte[] firmwareRevision, int size);

        [DllImport(LibraryName, EntryPoint = "AidlabSDK_destroy", CallingConvention = CallingConvention.Cdecl)]
        public static extern void AidlabSDK_destroy(IntPtr aidlabSdk);

        [DllImport(LibraryName, EntryPoint = "AidlabSDK_set_context", CallingConvention = CallingConvention.Cdecl)]
        public static extern void AidlabSDK_set_context(IntPtr context, IntPtr aidlabSdk);

        [DllImport(LibraryName, EntryPoint = "AidlabSDK_init_callbacks", CallingConvention = CallingConvention.Cdecl)]
        public static extern void AidlabSDK_init_callbacks(
            callbackSampleTime ecg,
            callbackSampleTime respiration,
            callbackSampleTime temperature,
            callbackAccelerometer accelerometer,
            callbackGyroscope gyroscope,
            callbackMagnetometer magnetometer,
            callbackBatteryLevel battery,
            callbackActivity activity,
            callbackSteps steps,
            callbackOrientation orientation,
            callbackQuaternion quaternion,
            callbackRespirationRate respirationRate,
            callbackWearState wearState,
            callbackHeartRate heartRate,
            callbackRr rr,
            callbackSoundVolume soundVolume,
            callbackExercise exercise,
            callbackUserEvent userEvent,
            callbackPressure pressure,
            callbackWearState pressureWearState,
            callbackBodyPosition bodyPosition,
            callbackSignalQuality signalQuality,
            IntPtr aidlabSdk);

        [DllImport(LibraryName, EntryPoint = "AidlabSDK_init_synchronization_callbacks", CallingConvention = CallingConvention.Cdecl)]
        public static extern void AidlabSDK_init_synchronization_callbacks(
            callbackSyncState syncState,
            callbackUnsynchronizedSize unsynchronizedSize,
            callbackSampleTime pastEcg,
            callbackSampleTime pastRespiration,
            callbackSampleTime pastTemperature,
            callbackHeartRate pastHeartRate,
            callbackRr pastRr,
            callbackActivity pastActivity,
            callbackRespirationRate pastRespirationRate,
            callbackSteps pastSteps,
            callbackUserEvent pastUserEvent,
            callbackSoundVolume pastSoundVolume,
            callbackPressure pastPressure,
            callbackAccelerometer pastAccelerometer,
            callbackGyroscope pastGyroscope,
            callbackQuaternion pastQuaternion,
            callbackOrientation pastOrientation,
            callbackMagnetometer pastMagnetometer,
            callbackBodyPosition pastBodyPosition,
            callbackSignalQuality pastSignalQuality,
            IntPtr aidlabSdk);

        [DllImport(LibraryName, EntryPoint = "AidlabSDK_set_eda_callback", CallingConvention = CallingConvention.Cdecl)]
        public static extern void AidlabSDK_set_eda_callback(callbackEda eda, IntPtr aidlabSdk);

        [DllImport(LibraryName, EntryPoint = "AidlabSDK_set_gps_callback", CallingConvention = CallingConvention.Cdecl)]
        public static extern void AidlabSDK_set_gps_callback(callbackGps gps, IntPtr aidlabSdk);

        [DllImport(LibraryName, EntryPoint = "AidlabSDK_set_past_eda_callback", CallingConvention = CallingConvention.Cdecl)]
        public static extern void AidlabSDK_set_past_eda_callback(callbackEda eda, IntPtr aidlabSdk);

        [DllImport(LibraryName, EntryPoint = "AidlabSDK_set_past_gps_callback", CallingConvention = CallingConvention.Cdecl)]
        public static extern void AidlabSDK_set_past_gps_callback(callbackGps gps, IntPtr aidlabSdk);

        [DllImport(LibraryName, EntryPoint = "AidlabSDK_set_payload_callback", CallingConvention = CallingConvention.Cdecl)]
        public static extern void AidlabSDK_set_payload_callback(callbackPayload callback, IntPtr aidlabSdk);

        [DllImport(LibraryName, EntryPoint = "AidlabSDK_set_log_callback", CallingConvention = CallingConvention.Cdecl)]
        public static extern void AidlabSDK_set_log_callback(callbackLogMessage callback, IntPtr context, IntPtr aidlabSdk);

        [DllImport(LibraryName, EntryPoint = "AidlabSDK_set_ble_send_callback", CallingConvention = CallingConvention.Cdecl)]
        public static extern void AidlabSDK_set_ble_send_callback(callbackBleSend callback, IntPtr aidlabSdk);

        [DllImport(LibraryName, EntryPoint = "AidlabSDK_set_ble_ready_callback", CallingConvention = CallingConvention.Cdecl)]
        public static extern void AidlabSDK_set_ble_ready_callback(callbackBleReady callback, IntPtr aidlabSdk);

        [DllImport(LibraryName, EntryPoint = "AidlabSDK_process_ble_chunk", CallingConvention = CallingConvention.Cdecl)]
        public static extern void AidlabSDK_process_ble_chunk(byte[] data, int size, IntPtr aidlabSdk);

        [DllImport(LibraryName, EntryPoint = "AidlabSDK_send", CallingConvention = CallingConvention.Cdecl)]
        public static extern void AidlabSDK_send(byte[] payload, int size, int processId, IntPtr aidlabSdk);
    }
}
