package Yoseen;

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.ptr.IntByReference;
import sun.misc.Unsafe;

import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;

public interface LibHK extends Library {
    LibHK Instance = Native.load(System.getProperty("user.dir") + "\\..\\build-Debug64\\LibHK.dll", LibHK.class);

    //////////////////////////////////////////////////////////////////////////////////////////////////////
    class LibHKclass {
        public static Unsafe __unsafe = null;

        public static int initSDK(String libDir) {
            //
            int ret;
            ret = LibHK.Instance.hkStaticInit(libDir);
            if (0 != ret) return ret;

            //
            try {
                Field field = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
                field.setAccessible(true);
                __unsafe = (sun.misc.Unsafe) field.get(null);
            } catch (Exception ex) {
                ret = EError.EError_InternalError;
            }
            return ret;
        }

        public static void freeSDK() {
            if (null == __unsafe) return;
            LibHK.Instance.hkStaticFree();
            __unsafe = null;
        }
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////
    long hkisapiCreate();

    void hkisapiFree(long pp);

    int hkisapiSetConfig(long context, long config);

    int hkisapiExecuteRaw(long context, long raw);

    int hkisapiExecuteRaw2(long context, long raw2);

    int hkisapiExecuteBin(long context, long bin);

    //////////////////////////////////////////////////////////////////////////////////////////////////////
    int hkStaticInit(String libDir);

    void hkStaticFree();

    long hkCreate();

    void hkFree(long pp);

    int hkLogin(long context, String ip, String username, String password);

    int hkLogout(long context);

    int hkPtzControl(long context, int act, int arg);

    int hkPtzControl_Stop(long context, int act, int arg);

    int hkPtzControl_GetPtz(long context, long pan, long tilt, long zoom, int timeout);

    int hkPtzControl_SetPtz(long context, int pan, int tilt, int zoom);

    int hkGetDVRConfig(long context, int cmd, int channel, long outBuffer, int outBufferSize, long bytesReturned);
    int hkSetDVRConfig(long context, int cmd, int channel, long inBuffer, int inBufferSize);
    int hkSTDXMLConfig(long context, long lpInputParam, long lpOutputParam);

    /*
    hkSerialStart(context, NULL, NULL) enable xptz
    */
    int hkSerialStart(long context, long cb, long cbData);

    int hkSerialStop(long context);

    int hkSerialSend(long context, long data, int dataSize);
    int hkSerialSendWaitRecv(long context, long req, int reqSize, long resp, IntByReference respSize, int timeout);

    //////////////////////////////////////////////////////////////////////////////////////////////////////
    class HKISAPIConfig {
        byte[] url = new byte[128];
        byte[] username = new byte[32];
        byte[] password = new byte[32];
        public short timeout;

        //
        public String url_str;
        public String username_str;
        public String password_str;
        //

        public HKISAPIConfig() {
            url_str="192.168.1.202";
            username_str="admin";
            password_str="yoseen2018";
            timeout = 2000;
        }

        public void toMem(long p) {
            //
            YoseenUtil.String2Bytes(url_str, url, 128);
            YoseenUtil.String2Bytes(username_str, username, 32);
            YoseenUtil.String2Bytes(password_str, password, 32);

            //
            Unsafe unsafe = LibHKclass.__unsafe;
            int i;
            for (i = 0; i < 128; i++) {
                unsafe.putByte(p, url[i]);
                p++;
            }

            for (i = 0; i < 32; i++) {
                unsafe.putByte(p, username[i]);
                p++;
            }

            for (i = 0; i < 32; i++) {
                unsafe.putByte(p, password[i]);
                p++;
            }

            unsafe.putShort(p, timeout);
        }

        public void fromMem(long p) {
            //
        }
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////
    class HKISAPI_ZoomFocus {
        public int pqrsZoom;
        public int mnstFocus;

        public void toMem(long p) {
            Unsafe unsafe = LibHKclass.__unsafe;
            unsafe.putInt(p, pqrsZoom);
            p += 4;
            unsafe.putInt(p, mnstFocus);
            p += 4;
        }

        public void fromMem(long p) {
            Unsafe unsafe = LibHKclass.__unsafe;
            pqrsZoom = unsafe.getInt(p);
            p += 4;
            mnstFocus = unsafe.getInt(p);
            p += 4;
        }
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////
    class HKISAPI_Color {
        public int brightnessLevel;//0,100
        public int contrastLevel;//0,100
        public int saturationLevel;//0,100

        public void toMem(long p) {
            Unsafe unsafe = LibHKclass.__unsafe;
            unsafe.putInt(p, brightnessLevel);
            p += 4;
            unsafe.putInt(p, contrastLevel);
            p += 4;
            unsafe.putInt(p, saturationLevel);
            p += 4;
        }

        public void fromMem(long p) {
            Unsafe unsafe = LibHKclass.__unsafe;
            brightnessLevel = unsafe.getInt(p);
            p += 4;
            contrastLevel = unsafe.getInt(p);
            p += 4;
            saturationLevel = unsafe.getInt(p);
            p += 4;
        }
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////
    class HKISAPI_Exposure {
        byte[] ExposureType = new byte[64];//"manual", "auto", "IrisFirst", "ShutterFirst"

        //
        public final static String[] All_ExposureType = new String[]{"manual", "auto", "IrisFirst", "ShutterFirst"};
        public String ExposureType_str;
        //

        public HKISAPI_Exposure() {
            ExposureType_str = All_ExposureType[0];
        }

        public void toMem(long p) {
            //
            YoseenUtil.String2Bytes(ExposureType_str, ExposureType, 64);

            //
            Unsafe unsafe = LibHKclass.__unsafe;
            int i;
            for (i = 0; i < 64; i++) {
                unsafe.putByte(p, ExposureType[i]);
                p++;
            }
        }

        public void fromMem(long p) {
            //
            Unsafe unsafe = LibHKclass.__unsafe;
            int len = 0;
            int i;
            for (i = 0; i < 64; i++) {
                ExposureType[i] = unsafe.getByte(p);
                p++;
            }

            //
            ExposureType_str = new String(ExposureType, 0, 64, StandardCharsets.US_ASCII);
        }
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////
    class HKISAPI_Iris {
        public int IrisLevel;//160, 200, 240, 280, 340, 400, 480, 560, 680, 960, 1100, 1400, 1600, 1900, 2200

        //
        public final static int[] All_IrisLevel = new int[]{160, 200, 240, 280, 340, 400, 480, 560, 680, 960, 1100, 1400, 1600, 1900, 2200};
        //

        public void toMem(long p) {
            Unsafe unsafe = LibHKclass.__unsafe;
            unsafe.putInt(p, IrisLevel);
            p += 4;
        }

        public void fromMem(long p) {
            Unsafe unsafe = LibHKclass.__unsafe;
            IrisLevel = unsafe.getInt(p);
            p += 4;
        }
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////
    class HKISAPI_FocusConfiguration {
        byte[] focusStyle = new byte[32];//AUTO,MANUAL,SEMIAUTOMATIC
        public int focusLimited;//10,30,100,150,300,600,1000,2000,65535

        //
        public final static String[] All_focusStyle = new String[]{"AUTO", "MANUAL", "SEMIAUTOMATIC"};
        public String focusStyle_str;
        //

        public HKISAPI_FocusConfiguration() {
            focusStyle_str = All_focusStyle[0];
        }

        public void toMem(long p) {
            //
            YoseenUtil.String2Bytes(focusStyle_str, focusStyle, 32);

            //
            Unsafe unsafe = LibHKclass.__unsafe;
            int i;
            for (i = 0; i < 32; i++) {
                unsafe.putByte(p, focusStyle[i]);
                p++;
            }
            unsafe.putInt(p, focusLimited);
        }

        public void fromMem(long p) {
            //
            Unsafe unsafe = LibHKclass.__unsafe;
            int i;
            for (i = 0; i < 32; i++) {
                focusStyle[i] = unsafe.getByte(p);
                p++;
            }
            focusLimited = unsafe.getInt(p);

            //
            focusStyle_str = new String(focusStyle, 0, 32, StandardCharsets.US_ASCII);
        }
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////
    class HKISAPI_SupplementLight {
        byte[] supplementLightMode = new byte[32];//close, colorVuWhiteLight
        byte[] mixedLightBrightnessRegulatMode = new byte[32];//manual, auto
        public int whiteLightBrightness;//[0,100]
        public int irLightBrightness;//[0,100]

        //
        public final static String[] All_SupplementLightMode = new String[]{"close", "colorVuWhiteLight"};
        public final static String[] All_MixedLightBrightnessRegulatMode = new String[]{"auto", "manual"};
        public String supplementLightMode_str;
        public String mixedLightBrightnessRegulatMode_str;
        //

        public HKISAPI_SupplementLight() {
            supplementLightMode_str = All_SupplementLightMode[0];
            mixedLightBrightnessRegulatMode_str = All_MixedLightBrightnessRegulatMode[0];
        }

        //
        public void toMem(long p) {
            //
            YoseenUtil.String2Bytes(supplementLightMode_str, supplementLightMode, 32);
            YoseenUtil.String2Bytes(mixedLightBrightnessRegulatMode_str, mixedLightBrightnessRegulatMode, 32);

            //
            Unsafe unsafe = LibHKclass.__unsafe;
            int i;
            for (i = 0; i < 32; i++) {
                unsafe.putByte(p, supplementLightMode[i]);
                p++;
            }
            for (i = 0; i < 32; i++) {
                unsafe.putByte(p, mixedLightBrightnessRegulatMode[i]);
                p++;
            }
            unsafe.putInt(p, whiteLightBrightness);
            p++;
            unsafe.putInt(p, irLightBrightness);
        }

        public void fromMem(long p) {
            //
            Unsafe unsafe = LibHKclass.__unsafe;
            int i;
            for (i = 0; i < 32; i++) {
                supplementLightMode[i] = unsafe.getByte(p);
                p++;
            }
            for (i = 0; i < 32; i++) {
                mixedLightBrightnessRegulatMode[i] = unsafe.getByte(p);
                p++;
            }
            whiteLightBrightness = unsafe.getInt(p);
            p++;
            irLightBrightness = unsafe.getInt(p);

            //
            supplementLightMode_str = new String(supplementLightMode, 0, 32, StandardCharsets.US_ASCII);
            mixedLightBrightnessRegulatMode_str = new String(mixedLightBrightnessRegulatMode, 0, 32, StandardCharsets.US_ASCII);
        }
    }

}
