/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.wifi.util;

import android.net.wifi.util.HexEncoding;
import android.text.TextUtils;

import com.android.server.wifi.ByteBufferReader;

import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;

/**
 * Provide utility functions for native interfacing modules.
 */
public class NativeUtil {
    private static final String ANY_MAC_STR = "any";
    public static final byte[] ANY_MAC_BYTES = {0, 0, 0, 0, 0, 0};
    private static final int MAC_LENGTH = 6;
    private static final int MAC_OUI_LENGTH = 3;
    private static final int MAC_STR_LENGTH = MAC_LENGTH * 2 + 5;
    private static final int SSID_BYTES_MAX_LEN = 32;

    /**
     * Convert the string to byte array list.
     *
     * @return the UTF_8 char byte values of str, as an ArrayList.
     * @throws IllegalArgumentException if a null or unencodable string is sent.
     */
    public static ArrayList<Byte> stringToByteArrayList(String str) {
        if (str == null) {
            throw new IllegalArgumentException("null string");
        }
        // Ensure that the provided string is UTF_8 encoded.
        CharsetEncoder encoder = StandardCharsets.UTF_8.newEncoder();
        try {
            ByteBuffer encoded = encoder.encode(CharBuffer.wrap(str));
            byte[] byteArray = new byte[encoded.remaining()];
            encoded.get(byteArray);
            return byteArrayToArrayList(byteArray);
        } catch (CharacterCodingException cce) {
            throw new IllegalArgumentException("cannot be utf-8 encoded", cce);
        }
    }

    /**
     * Convert the byte array list to string.
     *
     * @return the string decoded from UTF_8 byte values in byteArrayList.
     * @throws IllegalArgumentException if a null byte array list is sent.
     */
    public static String stringFromByteArrayList(ArrayList<Byte> byteArrayList) {
        if (byteArrayList == null) {
            throw new IllegalArgumentException("null byte array list");
        }
        byte[] byteArray = new byte[byteArrayList.size()];
        int i = 0;
        for (Byte b : byteArrayList) {
            byteArray[i] = b;
            i++;
        }
        return new String(byteArray, StandardCharsets.UTF_8);
    }

    /**
     * Convert the string to byte array.
     *
     * @return the UTF_8 char byte values of str, as an Array.
     * @throws IllegalArgumentException if a null string is sent.
     */
    public static byte[] stringToByteArray(String str) {
        if (str == null) {
            throw new IllegalArgumentException("null string");
        }
        return str.getBytes(StandardCharsets.UTF_8);
    }

    /**
     * Convert the byte array list to string.
     *
     * @return the string decoded from UTF_8 byte values in byteArray.
     * @throws IllegalArgumentException if a null byte array is sent.
     */
    public static String stringFromByteArray(byte[] byteArray) {
        if (byteArray == null) {
            throw new IllegalArgumentException("null byte array");
        }
        return new String(byteArray);
    }

    /**
     * Converts a mac address string to an array of Bytes.
     *
     * @param macStr string of format: "XX:XX:XX:XX:XX:XX" or "XXXXXXXXXXXX", where X is any
     *        hexadecimal digit.
     *        Passing null, empty string or "any" is the same as 00:00:00:00:00:00
     * @throws IllegalArgumentException for various malformed inputs.
     */
    public static byte[] macAddressToByteArray(String macStr) {
        if (TextUtils.isEmpty(macStr) || ANY_MAC_STR.equals(macStr)) return ANY_MAC_BYTES;
        String cleanMac = macStr.replace(":", "");
        if (cleanMac.length() != MAC_LENGTH * 2) {
            throw new IllegalArgumentException("invalid mac string length: " + cleanMac);
        }
        return HexEncoding.decode(cleanMac.toCharArray(), false);
    }

    /**
     * Converts an array of 6 bytes to a HexEncoded String with format: "XX:XX:XX:XX:XX:XX", where X
     * is any hexadecimal digit.
     *
     * @param macArray byte array of mac values, must have length 6
     * @throws IllegalArgumentException for malformed inputs.
     */
    public static String macAddressFromByteArray(byte[] macArray) {
        if (macArray == null) {
            throw new IllegalArgumentException("null mac bytes");
        }
        if (macArray.length != MAC_LENGTH) {
            throw new IllegalArgumentException("invalid macArray length: " + macArray.length);
        }
        StringBuilder sb = new StringBuilder(MAC_STR_LENGTH);
        for (int i = 0; i < macArray.length; i++) {
            if (i != 0) sb.append(":");
            sb.append(new String(HexEncoding.encode(macArray, i, 1)));
        }
        return sb.toString().toLowerCase();
    }

    /**
     * Converts a mac address OUI string to an array of Bytes.
     *
     * @param macStr string of format: "XX:XX:XX" or "XXXXXX", where X is any hexadecimal digit.
     * @throws IllegalArgumentException for various malformed inputs.
     */
    public static byte[] macAddressOuiToByteArray(String macStr) {
        if (macStr == null) {
            throw new IllegalArgumentException("null mac string");
        }
        String cleanMac = macStr.replace(":", "");
        if (cleanMac.length() != MAC_OUI_LENGTH * 2) {
            throw new IllegalArgumentException("invalid mac oui string length: " + cleanMac);
        }
        return HexEncoding.decode(cleanMac.toCharArray(), false);
    }

    /**
     * Converts an array of 6 bytes to a long representing the MAC address.
     *
     * @param macArray byte array of mac values, must have length 6
     * @return Long value of the mac address.
     * @throws IllegalArgumentException for malformed inputs.
     */
    public static Long macAddressToLong(byte[] macArray) {
        if (macArray == null) {
            throw new IllegalArgumentException("null mac bytes");
        }
        if (macArray.length != MAC_LENGTH) {
            throw new IllegalArgumentException("invalid macArray length: " + macArray.length);
        }
        try {
            return ByteBufferReader.readInteger(
                    ByteBuffer.wrap(macArray), ByteOrder.BIG_ENDIAN, macArray.length);
        } catch (BufferUnderflowException | IllegalArgumentException e) {
            throw new IllegalArgumentException("invalid macArray");
        }
    }

    /**
     * Remove enclosing quotes from the provided string.
     *
     * @param quotedStr String to be unquoted.
     * @return String without the enclosing quotes.
     */
    public static String removeEnclosingQuotes(String quotedStr) {
        int length = quotedStr.length();
        if ((length >= 2)
                && (quotedStr.charAt(0) == '"') && (quotedStr.charAt(length - 1) == '"')) {
            return quotedStr.substring(1, length - 1);
        }
        return quotedStr;
    }

    /**
     * Add enclosing quotes to the provided string.
     *
     * @param str String to be quoted.
     * @return String with the enclosing quotes.
     */
    public static String addEnclosingQuotes(String str) {
        return "\"" + str + "\"";
    }

    /**
     * Converts an string to an arraylist of UTF_8 byte values.
     * These forms are acceptable:
     * a) UTF-8 String encapsulated in quotes, or
     * b) Hex string with no delimiters.
     *
     * @param str String to be converted.
     * @throws IllegalArgumentException for null string.
     */
    public static ArrayList<Byte> hexOrQuotedStringToBytes(String str) {
        if (str == null) {
            throw new IllegalArgumentException("null string");
        }
        int length = str.length();
        if ((length > 1) && (str.charAt(0) == '"') && (str.charAt(length - 1) == '"')) {
            str = str.substring(1, str.length() - 1);
            return stringToByteArrayList(str);
        } else {
            return byteArrayToArrayList(hexStringToByteArray(str));
        }
    }

    /**
     * Converts an ArrayList<Byte> of UTF_8 byte values to string.
     * The string will either be:
     * a) UTF-8 String encapsulated in quotes (if all the bytes are UTF-8 encodeable and non null),
     * or
     * b) Hex string with no delimiters.
     *
     * @param bytes List of bytes for ssid.
     * @throws IllegalArgumentException for null bytes.
     */
    public static String bytesToHexOrQuotedString(ArrayList<Byte> bytes) {
        if (bytes == null) {
            throw new IllegalArgumentException("null ssid bytes");
        }
        byte[] byteArray = byteArrayFromArrayList(bytes);
        // Check for 0's in the byte stream in which case we cannot convert this into a string.
        if (!bytes.contains(Byte.valueOf((byte) 0))) {
            CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder();
            try {
                CharBuffer decoded = decoder.decode(ByteBuffer.wrap(byteArray));
                return "\"" + decoded.toString() + "\"";
            } catch (CharacterCodingException cce) {
            }
        }
        return hexStringFromByteArray(byteArray);
    }

    /**
     * Converts an ssid string to an arraylist of UTF_8 byte values.
     * These forms are acceptable:
     * a) UTF-8 String encapsulated in quotes, or
     * b) Hex string with no delimiters.
     *
     * @param ssidStr String to be converted.
     * @throws IllegalArgumentException for null string.
     */
    public static ArrayList<Byte> decodeSsid(String ssidStr) {
        ArrayList<Byte> ssidBytes = hexOrQuotedStringToBytes(ssidStr);
        if (ssidBytes.size() > SSID_BYTES_MAX_LEN) {
            throw new IllegalArgumentException("ssid bytes size out of range: " + ssidBytes.size());
        }
        return ssidBytes;
    }

    /**
     * Converts an ArrayList<Byte> of UTF_8 byte values to ssid string.
     * The string will either be:
     * a) UTF-8 String encapsulated in quotes (if all the bytes are UTF-8 encodeable and non null),
     * or
     * b) Hex string with no delimiters.
     *
     * @param ssidBytes List of bytes for ssid.
     * @throws IllegalArgumentException for null bytes.
     */
    public static String encodeSsid(ArrayList<Byte> ssidBytes) {
        if (ssidBytes.size() > SSID_BYTES_MAX_LEN) {
            throw new IllegalArgumentException("ssid bytes size out of range: " + ssidBytes.size());
        }
        return bytesToHexOrQuotedString(ssidBytes);
    }

    /**
     * Convert from an array of primitive bytes to an array list of Byte.
     */
    public static ArrayList<Byte> byteArrayToArrayList(byte[] bytes) {
        ArrayList<Byte> byteList = new ArrayList<>();
        for (Byte b : bytes) {
            byteList.add(b);
        }
        return byteList;
    }

    /**
     * Convert from an array list of Byte to an array of primitive bytes.
     */
    public static byte[] byteArrayFromArrayList(ArrayList<Byte> bytes) {
        byte[] byteArray = new byte[bytes.size()];
        int i = 0;
        for (Byte b : bytes) {
            byteArray[i++] = b;
        }
        return byteArray;
    }

    /**
     * Converts a hex string to byte array.
     *
     * @param hexStr String to be converted.
     * @throws IllegalArgumentException for null string.
     */
    public static byte[] hexStringToByteArray(String hexStr) {
        if (hexStr == null) {
            throw new IllegalArgumentException("null hex string");
        }
        return HexEncoding.decode(hexStr.toCharArray(), false);
    }

    /**
     * Converts a byte array to hex string.
     *
     * @param bytes List of bytes for ssid.
     * @throws IllegalArgumentException for null bytes.
     */
    public static String hexStringFromByteArray(byte[] bytes) {
        if (bytes == null) {
            throw new IllegalArgumentException("null hex bytes");
        }
        return new String(HexEncoding.encode(bytes)).toLowerCase();
    }

    /**
     * Converts an 8 byte array to a WPS device type string
     * { 0, 1, 2, -1, 4, 5, 6, 7 } --> "1-02FF0405-1543";
     */
    public static String wpsDevTypeStringFromByteArray(byte[] devType) {
        byte[] a = devType;
        int x = ((a[0] & 0xFF) << 8) | (a[1] & 0xFF);
        String y = new String(HexEncoding.encode(Arrays.copyOfRange(devType, 2, 6)));
        int z = ((a[6] & 0xFF) << 8) | (a[7] & 0xFF);
        return String.format("%d-%s-%d", x, y, z);
    }
}
