/*
 * Copyright (C) 2019 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.car;

import static com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport.BOILERPLATE_CODE;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.util.SparseArray;

import com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;

/**
 * Some potentially useful static methods.
 */
public class Utils {
    static final Boolean DBG = false;
    // https://developer.android.com/reference/java/util/UUID
    private static final int UUID_LENGTH = 16;


    /*
     * Maps of types and status to human readable strings
     */

    private static final SparseArray<String> sAdapterStates = new SparseArray<String>();
    private static final SparseArray<String> sBondStates = new SparseArray<String>();
    private static final SparseArray<String> sConnectionStates = new SparseArray<String>();
    private static final SparseArray<String> sProfileNames = new SparseArray<String>();
    static {

        // Bluetooth Adapter states
        sAdapterStates.put(BluetoothAdapter.STATE_ON, "On");
        sAdapterStates.put(BluetoothAdapter.STATE_OFF, "Off");
        sAdapterStates.put(BluetoothAdapter.STATE_TURNING_ON, "Turning On");
        sAdapterStates.put(BluetoothAdapter.STATE_TURNING_OFF, "Turning Off");

        // Device Bonding states
        sBondStates.put(BluetoothDevice.BOND_BONDED, "Bonded");
        sBondStates.put(BluetoothDevice.BOND_BONDING, "Bonding");
        sBondStates.put(BluetoothDevice.BOND_NONE, "Unbonded");

        // Device and Profile Connection states
        sConnectionStates.put(BluetoothAdapter.STATE_CONNECTED, "Connected");
        sConnectionStates.put(BluetoothAdapter.STATE_DISCONNECTED, "Disconnected");
        sConnectionStates.put(BluetoothAdapter.STATE_CONNECTING, "Connecting");
        sConnectionStates.put(BluetoothAdapter.STATE_DISCONNECTING, "Disconnecting");

        // Profile Names
        sProfileNames.put(BluetoothProfile.HEADSET, "HFP Server");
        sProfileNames.put(BluetoothProfile.A2DP, "A2DP Source");
        sProfileNames.put(BluetoothProfile.HEALTH, "HDP");
        sProfileNames.put(BluetoothProfile.HID_HOST, "HID Host");
        sProfileNames.put(BluetoothProfile.PAN, "PAN");
        sProfileNames.put(BluetoothProfile.PBAP, "PBAP Server");
        sProfileNames.put(BluetoothProfile.GATT, "GATT Client");
        sProfileNames.put(BluetoothProfile.GATT_SERVER, "GATT Server");
        sProfileNames.put(BluetoothProfile.MAP, "MAP Server");
        sProfileNames.put(BluetoothProfile.SAP, "SAP");
        sProfileNames.put(BluetoothProfile.A2DP_SINK, "A2DP Sink");
        sProfileNames.put(BluetoothProfile.AVRCP_CONTROLLER, "AVRCP Controller");
        sProfileNames.put(BluetoothProfile.AVRCP, "AVRCP Target");
        sProfileNames.put(BluetoothProfile.HEADSET_CLIENT, "HFP Client");
        sProfileNames.put(BluetoothProfile.PBAP_CLIENT, "PBAP Client");
        sProfileNames.put(BluetoothProfile.MAP_CLIENT, "MAP Client");
        sProfileNames.put(BluetoothProfile.HID_DEVICE, "HID Device");
        sProfileNames.put(BluetoothProfile.OPP, "OPP");
        sProfileNames.put(BluetoothProfile.HEARING_AID, "Hearing Aid");
    }

    static String getDeviceDebugInfo(BluetoothDevice device) {
        if (device == null) {
            return "(null)";
        }
        return "(name = " + device.getName() + ", addr = " + device.getAddress() + ")";
    }

    static String getProfileName(int profile) {
        String name = sProfileNames.get(profile, "Unknown");
        return "(" + profile + ") " + name;
    }

    static String getConnectionStateName(int state) {
        String name = sConnectionStates.get(state, "Unknown");
        return "(" + state + ") " + name;
    }

    static String getBondStateName(int state) {
        String name = sBondStates.get(state, "Unknown");
        return "(" + state + ") " + name;
    }

    static String getAdapterStateName(int state) {
        String name = sAdapterStates.get(state, "Unknown");
        return "(" + state + ") " + name;
    }

    static String getProfilePriorityName(int priority) {
        String name = "";
        if (priority >= BluetoothProfile.PRIORITY_AUTO_CONNECT) {
            name = "PRIORITY_AUTO_CONNECT";
        } else if (priority >= BluetoothProfile.PRIORITY_ON) {
            name = "PRIORITY_ON";
        } else if (priority >= BluetoothProfile.PRIORITY_OFF) {
            name = "PRIORITY_OFF";
        } else {
            name = "PRIORITY_UNDEFINED";
        }
        return "(" + priority + ") " + name;
    }

    /**
     * An utility class to dump transition events across different car service components.
     * The output will be of the form
     * <p>
     * "Time <svc name>: [optional context information] changed from <from state> to <to state>"
     * This can be used in conjunction with the dump() method to dump this information through
     * adb shell dumpsys activity service com.android.car
     * <p>
     * A specific service in CarService can choose to use a circular buffer of N records to keep
     * track of the last N transitions.
     */
    public static final class TransitionLog {
        private String mServiceName; // name of the service or tag
        private Object mFromState; // old state
        private Object mToState; // new state
        private long mTimestampMs; // System.currentTimeMillis()
        private String mExtra; // Additional information as a String

        public TransitionLog(String name, Object fromState, Object toState, long timestamp,
                String extra) {
            this(name, fromState, toState, timestamp);
            mExtra = extra;
        }

        public TransitionLog(String name, Object fromState, Object toState, long timeStamp) {
            mServiceName = name;
            mFromState = fromState;
            mToState = toState;
            mTimestampMs = timeStamp;
        }

        private CharSequence timeToLog(long timestamp) {
            return android.text.format.DateFormat.format("MM-dd HH:mm:ss", timestamp);
        }

        @Override
        public String toString() {
            return timeToLog(mTimestampMs) + " " + mServiceName + ": "
                    + (mExtra != null ? mExtra + " " : "")
                    + "changed from " + mFromState + " to " + mToState;
        }
    }

    /**
     * Returns a byte buffer corresponding to the passed long argument.
     *
     * @param primitive data to convert format.
     */
    public static byte[] longToBytes(long primitive) {
        ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
        buffer.putLong(primitive);
        return buffer.array();
    }

    /**
     * Returns a byte buffer corresponding to the passed long argument.
     *
     * @param array data to convert format.
     */
    public static long bytesToLong(byte[] array) {
        ByteBuffer buffer = ByteBuffer.allocate(Long.SIZE / Byte.SIZE);
        buffer.put(array);
        buffer.flip();
        long value = buffer.getLong();
        return value;
    }

    /**
     * Returns a String in Hex format that is formed from the bytes in the byte array
     * Useful for debugging
     *
     * @param array the byte array
     * @return the Hex string version of the input byte array
     */
    public static String byteArrayToHexString(byte[] array) {
        StringBuilder sb = new StringBuilder(array.length * 2);
        for (byte b : array) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }

    /**
     * Convert UUID to Big Endian byte array
     *
     * @param uuid UUID to convert
     * @return the byte array representing the UUID
     */
    @NonNull
    public static byte[] uuidToBytes(@NonNull UUID uuid) {

        return ByteBuffer.allocate(UUID_LENGTH)
                .order(ByteOrder.BIG_ENDIAN)
                .putLong(uuid.getMostSignificantBits())
                .putLong(uuid.getLeastSignificantBits())
                .array();
    }

    /**
     * Convert Big Endian byte array to UUID
     *
     * @param bytes byte array to convert
     * @return the UUID representing the byte array, or null if not a valid UUID
     */
    @Nullable
    public static UUID bytesToUUID(@NonNull byte[] bytes) {
        if (bytes.length != UUID_LENGTH) {
            return null;
        }

        ByteBuffer buffer = ByteBuffer.wrap(bytes);
        return new UUID(buffer.getLong(), buffer.getLong());
    }

    /**
     * Generate a random zero-filled string of given length
     *
     * @param length of string
     * @return generated string
     */
    @SuppressLint("DefaultLocale")  // Should always have the same format regardless of locale
    public static String generateRandomNumberString(int length) {
        return String.format("%0" + length + "d",
                ThreadLocalRandom.current().nextInt((int) Math.pow(10, length)));
    }


    /**
     * Concatentate the given 2 byte arrays
     *
     * @param a input array 1
     * @param b input array 2
     * @return concatenated array of arrays 1 and 2
     */
    @Nullable
    public static byte[] concatByteArrays(@Nullable byte[] a, @Nullable byte[] b) {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        try {
            if (a != null) {
                outputStream.write(a);
            }
            if (b != null) {
                outputStream.write(b);
            }
        } catch (IOException e) {
            return null;
        }
        return outputStream.toByteArray();
    }

    @ExcludeFromCodeCoverageGeneratedReport(reason = BOILERPLATE_CODE,
            details = "private constructor")
    private Utils() {
        throw new UnsupportedOperationException("contains only static methods");
    }
}
