package netmanager.lib;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Array;

import com.sun.jna.Memory;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;


// 数据类型操作类
public class DataUtils {
    /////////////////////////////////////////////////////////////////////////////////////////////////

    // 本地化代码数据指针转换为 JAVA 数据结构
    public static void sdk_data_ptrToStructure(Pointer ptr, Structure structure) {
        sdk_data_ptrToStructure(ptr, 0, structure);
    }

    // 本地化代码数据指针转换为 JAVA 数据结构
    public static void sdk_data_ptrToStructure(Pointer ptr, long offset, Structure structure) {
        structure.write();
        Pointer ptrMemory = structure.getPointer();
        ptrMemory.write(0, ptr.getByteArray(offset, structure.size()), 0, structure.size());
        structure.read();
    }

    // 本地化代码数据指针转换为 JAVA 数据结构数组
    public static void sdk_data_ptrToStructureArray(Pointer ptr, Structure[] array) {
        long offset = 0;
        for (int i = 0; i < array.length; i++) {
            sdk_data_ptrToStructure(ptr, offset, array[i]);
            offset += array[i].size();
        }
    }

    // JAVA 数据结构转换为本地化代码数据结构
    public static void sdk_data_structureToPtr(Structure structure, Pointer ptr, long offset) {
        structure.write();
        Pointer ptrMemory = structure.getPointer();
        ptr.write(offset, ptrMemory.getByteArray(0, structure.size()), 0, structure.size());
    }

    // JAVA 数据结构数组转换为本地化代码数据结构数组
    public static void sdk_data_structureArrayToPtr(Structure[] array, Pointer ptr) {
        long offset = 0;
        for (int i = 0; i < array.length; i++) {
            sdk_data_structureToPtr(array[i], ptr, offset);
            offset += array[i].size();
        }
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////
    // 泛型类型数组
    public static class GenericTypeArray<T> {
        private T[] array;

        @SuppressWarnings("unchecked")
        public GenericTypeArray(Class<T> type, int sz) {
            array = (T[]) Array.newInstance(type, sz);
        }

        public void put(int index, T item) {
            array[index] = item;
        }

        public T get(int index) {
            return array[index];
        }

        public T[] get() {
            return array;
        }
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////
    // 创建Pointer
    public static Pointer sdk_data_createPtr(int length) {
        if (0 >= length) {
            return null;
        }

        Pointer ptr = new Memory(length);

        for (int i = 0; i < length; i++) {
            ptr.setByte(i, (byte) 0);
        }

        return ptr;
    }

    // Pointer拷贝
    public static void sdk_data_copyPtr(Pointer dst, Pointer src, int length) {
        if (0 >= length) {
            return;
        }

        for (int i = 0; i < length; i++) {
            dst.setByte(i, src.getByte(i));
        }
    }

    // 将 Pointer 值转为 byte[]
    public static byte[] sdk_data_ptrToByteArray(Pointer ptr, int offset, int length) {
        if (null == ptr || 0 > offset || 0 >= length) {
            return null;
        }

        byte[] array = new byte[length];
        for (int i = 0; i < length; i++) {
            Array.setByte(array, i, (byte) 0);
        }

        ptr.read(offset, array, 0, length);
        return array;
    }

    // byte 数组转换为 Pointer
    public static Pointer sdk_data_byteArrayToPtr(byte[] array) {
        if (null == array || 0 == array.length)
            return null;

        Pointer ptr = new Memory(array.length);
        ptr.write(0, array, 0, array.length);
        return ptr;
    }

    // byte 数组转换为字符串，charset 为字符集名称，如 GBK,UTF-8
    public static String sdk_data_byteArrayToString(byte[] array, String charset) {
        if (null == array || 0 == array.length)
            return null;

        String encoding = (null == charset || charset.isEmpty()) ? "UTF-8" : charset;
        String dst = null;
        try {
            dst = new String(array, encoding).trim();
        } catch (Exception ex) {
            dst = null;
        }

        return dst;
    }

    // 字符串转换为 byte 数组，charset 为字符集名称，如 GBK,UTF-8
    public static byte[] sdk_data_stringToByteArray(String text, String charset) {
        if (null == text || text.isEmpty())
            return null;

        String encoding = (null == charset || charset.isEmpty()) ? "UTF-8" : charset;
        byte[] array = null;
        try {
            array = text.getBytes(encoding);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return null;
        }
        return array;
    }

    // 字符串数据拷贝到 byte 数组，charset 为字符集名称，如 GBK,UTF-8
    public static boolean sdk_data_copyStringToByteArray(byte[] dst, String src, int nOffset, String charset) {
        if (null == src || src.isEmpty() || null == dst || 0 >= dst.length)
            return false;

        String encoding = (null == charset || charset.isEmpty()) ? "UTF-8" : charset;
        byte[] array = null;
        try {
            array = src.getBytes(encoding);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return false;
        }

        for (int i = 0; i < dst.length; i++) {
            dst[i] = 0x00;
        }

        try {
            System.arraycopy(array, nOffset, dst, nOffset, array.length);
        } catch (IndexOutOfBoundsException | ArrayStoreException | NullPointerException e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    // Pointer 指向的内存数据转换为字符串，charset 为字符集名称，如 GBK,UTF-8
    public static String sdk_data_ptrToString(Pointer ptr, int offset, int length, String charset) {
        byte[] array = sdk_data_ptrToByteArray(ptr, offset, length);
        return sdk_data_byteArrayToString(array, charset);
    }

    // 字符串转换为 Pointer，charset 为字符集名称，如 GBK,UTF-8
    public static Pointer sdk_data_stringToPtr(String text, String charset) {
        if (null == text || text.isEmpty())
            return null;

        String encoding = (null == charset || charset.isEmpty()) ? "UTF-8" : charset;
        byte[] array = null;
        Pointer ptr = null;
        try {
            array = text.getBytes(encoding);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return null;
        }

        ptr = sdk_data_byteArrayToPtr(array);
        return ptr;
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////

    // char[] to byte[]
    public static byte[] sdk_data_charArrayToByteArray(char[] chars) {
        if (null == chars || 0 == chars.length)
            return null;

        byte[] bytes = new byte[chars.length];
        for (int i = 0; i < chars.length; i++) {
            bytes[i] = (byte) chars[i];
        }

        return bytes;
    }

    // byte[] to char[]
    public static char[] sdk_data_byteArrayToCharArray(byte[] bytes) {
        if (null == bytes || 0 == bytes.length)
            return null;

        char[] chars = new char[bytes.length];
        for (int i = 0; i < bytes.length; i++) {
            chars[i] = (char) bytes[i];
        }

        return chars;
    }

    public static String sdk_data_intToBinaryString(int n, int nBitCount) {
        if (n < 0 || nBitCount < 0)
            return "";

        String strBinaryString = Integer.toBinaryString(n);
        while (strBinaryString.length() < nBitCount) {
            strBinaryString = "0" + strBinaryString;
        }

        return strBinaryString;
    }

    public static int sdk_data_stringToInt(String str) {
        if (str.isEmpty())
            return 0;

        return Integer.parseInt(str);
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////

    public static boolean sdk_data_fileExist(String filename) {
        File file = null;

        try {
            file = new File(filename);
        } catch (Exception ex) {
            return false;
        }

        if (!file.exists() && !file.isDirectory()) {
            return false;
        }

        return true;
    }

    // 将文本数据写入指定文件
    public static boolean sdk_data_fileWrite(char[] data, String filename, boolean append, String charset) {
        if (null == data || 0 == data.length || null == filename || filename.isEmpty())
            return false;

        File file = null;

        try {
            file = new File(filename);

            if (!file.exists()) {
                file.createNewFile();
            }

            FileWriter fw = new FileWriter(file.getName(), append);
            fw.write(data, 0, data.length);
            ;
            fw.close();

            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    // 将数据写入指定文件
    public static boolean sdk_data_fileWrite(byte[] data, String filename) {
        FileOutputStream fos = null;

        try {
            fos = new FileOutputStream(filename);
            fos.write(data);
            fos.close();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    // 将数据写入指定文件
    public static boolean sdk_data_fileWrite(byte[] data, int offset, int length, String filename) {
        FileOutputStream fos = null;

        try {
            fos = new FileOutputStream(filename);
            fos.write(data, offset, length);
            fos.close();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    // 将数据写入指定文件
    public static boolean sdk_data_fileWrite(Pointer ptr, int ptrOffset, int wOffset, int length, String filename) {
        FileOutputStream fos = null;

        try {
            fos = new FileOutputStream(filename);
            fos.write(ptr.getByteArray(ptrOffset, length), wOffset, length);
            fos.close();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    public static byte[] sdk_data_fileRead(String filename) {
        File inFile = new File(filename);
        FileInputStream streamIn = null;

        try {
            streamIn = new FileInputStream(inFile);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        int nByteLength = (int) inFile.length();

        int byData;
        byte[] tmpByArr = new byte[nByteLength];
        int nIndex = 0;
        try {
            while (-1 != (byData = streamIn.read())) {
                tmpByArr[nIndex] = (byte) byData;
                nIndex++;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            streamIn.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return tmpByArr;
    }
}