package android.net.wifi;

import android.annotation.SystemApi;
import android.content.Context;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
import android.util.SparseArray;

import com.android.internal.util.AsyncChannel;

import java.util.concurrent.CountDownLatch;

/** @hide */
@SystemApi
public class RttManager {

    private static final boolean DBG = true;
    private static final String TAG = "RttManager";

    public static final int RTT_TYPE_UNSPECIFIED    = 0;
    public static final int RTT_TYPE_ONE_SIDED      = 1;
    public static final int RTT_TYPE_11_V           = 2;
    public static final int RTT_TYPE_11_MC          = 4;

    public static final int RTT_PEER_TYPE_UNSPECIFIED    = 0;
    public static final int RTT_PEER_TYPE_AP             = 1;
    public static final int RTT_PEER_TYPE_STA            = 2;       /* requires NAN */

    public static final int RTT_CHANNEL_WIDTH_20      = 0;
    public static final int RTT_CHANNEL_WIDTH_40      = 1;
    public static final int RTT_CHANNEL_WIDTH_80      = 2;
    public static final int RTT_CHANNEL_WIDTH_160     = 3;
    public static final int RTT_CHANNEL_WIDTH_80P80   = 4;
    public static final int RTT_CHANNEL_WIDTH_5       = 5;
    public static final int RTT_CHANNEL_WIDTH_10      = 6;
    public static final int RTT_CHANNEL_WIDTH_UNSPECIFIED = -1;

    public static final int RTT_STATUS_SUCCESS                  = 0;
    public static final int RTT_STATUS_FAILURE                  = 1;
    public static final int RTT_STATUS_FAIL_NO_RSP              = 2;
    public static final int RTT_STATUS_FAIL_REJECTED            = 3;
    public static final int RTT_STATUS_FAIL_NOT_SCHEDULED_YET   = 4;
    public static final int RTT_STATUS_FAIL_TM_TIMEOUT          = 5;
    public static final int RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL  = 6;
    public static final int RTT_STATUS_FAIL_NO_CAPABILITY       = 7;
    public static final int RTT_STATUS_ABORTED                  = 8;

    public static final int REASON_UNSPECIFIED              = -1;
    public static final int REASON_INVALID_LISTENER         = -2;
    public static final int REASON_INVALID_REQUEST          = -3;

    public class Capabilities {
        int supportedType;
        int supportedPeerType;
    }

    public Capabilities getCapabilities() {
        return new Capabilities();
    }

    /** specifies parameters for RTT request */
    public static class RttParams {

        /** type of device being ranged; one of RTT_PEER_TYPE_AP or RTT_PEER_TYPE_STA */
        public int deviceType;

        /** type of RTT being sought; one of RTT_TYPE_ONE_SIDED
         *  RTT_TYPE_11_V or RTT_TYPE_11_MC or RTT_TYPE_UNSPECIFIED */
        public int requestType;

        /** mac address of the device being ranged */
        public String bssid;

        /** channel frequency that the device is on; optional */
        public int frequency;

        /** optional channel width. wider channels result in better accuracy,
         *  but they take longer time, and even get aborted may times; use
         *  RTT_CHANNEL_WIDTH_UNSPECIFIED if not specifying */
        public int channelWidth;

        /** number of samples to be taken */
        public int num_samples;

        /** number of retries if a sample fails */
        public int num_retries;
    }

    /** specifies RTT results */
    public static class RttResult {
        /** mac address of the device being ranged */
        public String bssid;

        /** status of the request */
        public int status;

        /** timestamp of completion, in microsecond since boot */
        public long ts;

        /** average RSSI observed */
        public int rssi;

        /** RSSI spread (i.e. max - min) */
        public int rssi_spread;

        /** average transmit rate */
        public int tx_rate;

        /** average round trip time in nano second */
        public long rtt_ns;

        /** standard deviation observed in round trip time */
        public long rtt_sd_ns;

        /** spread (i.e. max - min) round trip time */
        public long rtt_spread_ns;

        /** average distance in centimeter, computed based on rtt_ns */
        public long distance_cm;

        /** standard deviation observed in distance */
        public long distance_sd_cm;

        /** spread (i.e. max - min) distance */
        public long distance_spread_cm;
    }

    public static interface RttListener {
        public void onSuccess(RttResult results[]);
        public void onFailure(int reason, String description);
        public void onAborted();
    }

    public void startRanging(RttParams params[], RttListener listener) {
        validateChannel();
        sAsyncChannel.sendMessage(CMD_OP_START_RANGING, 0, removeListener(listener), params);
    }

    public void stopRanging(RttListener listener) {
        validateChannel();
        sAsyncChannel.sendMessage(CMD_OP_STOP_RANGING, 0, removeListener(listener));
    }

    /* private methods */
    public static final int CMD_OP_START_RANGING        = 0;
    public static final int CMD_OP_STOP_RANGING         = 1;
    public static final int CMD_OP_FAILED               = 2;
    public static final int CMD_OP_SUCCEEDED            = 3;
    public static final int CMD_OP_ABORTED              = 4;

    private Context mContext;
    private IRttManager mService;

    private static final int INVALID_KEY = 0;
    private static int sListenerKey = 1;

    private static final SparseArray sListenerMap = new SparseArray();
    private static final Object sListenerMapLock = new Object();

    private static AsyncChannel sAsyncChannel;
    private static CountDownLatch sConnected;

    private static final Object sThreadRefLock = new Object();
    private static int sThreadRefCount;
    private static HandlerThread sHandlerThread;

    /**
     * Create a new WifiScanner instance.
     * Applications will almost always want to use
     * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
     * the standard {@link android.content.Context#WIFI_SERVICE Context.WIFI_SERVICE}.
     * @param context the application context
     * @param service the Binder interface
     * @hide
     */

    public RttManager(Context context, IRttManager service) {
        mContext = context;
        mService = service;
        init();
    }

    private void init() {
        synchronized (sThreadRefLock) {
            if (++sThreadRefCount == 1) {
                Messenger messenger = null;
                try {
                    messenger = mService.getMessenger();
                } catch (RemoteException e) {
                    /* do nothing */
                } catch (SecurityException e) {
                    /* do nothing */
                }

                if (messenger == null) {
                    sAsyncChannel = null;
                    return;
                }

                sHandlerThread = new HandlerThread("WifiScanner");
                sAsyncChannel = new AsyncChannel();
                sConnected = new CountDownLatch(1);

                sHandlerThread.start();
                Handler handler = new ServiceHandler(sHandlerThread.getLooper());
                sAsyncChannel.connect(mContext, handler, messenger);
                try {
                    sConnected.await();
                } catch (InterruptedException e) {
                    Log.e(TAG, "interrupted wait at init");
                }
            }
        }
    }

    private void validateChannel() {
        if (sAsyncChannel == null) throw new IllegalStateException(
                "No permission to access and change wifi or a bad initialization");
    }

    private static int putListener(Object listener) {
        if (listener == null) return INVALID_KEY;
        int key;
        synchronized (sListenerMapLock) {
            do {
                key = sListenerKey++;
            } while (key == INVALID_KEY);
            sListenerMap.put(key, listener);
        }
        return key;
    }

    private static Object getListener(int key) {
        if (key == INVALID_KEY) return null;
        synchronized (sListenerMapLock) {
            Object listener = sListenerMap.get(key);
            return listener;
        }
    }

    private static int getListenerKey(Object listener) {
        if (listener == null) return INVALID_KEY;
        synchronized (sListenerMapLock) {
            int index = sListenerMap.indexOfValue(listener);
            if (index == -1) {
                return INVALID_KEY;
            } else {
                return sListenerMap.keyAt(index);
            }
        }
    }

    private static Object removeListener(int key) {
        if (key == INVALID_KEY) return null;
        synchronized (sListenerMapLock) {
            Object listener = sListenerMap.get(key);
            sListenerMap.remove(key);
            return listener;
        }
    }

    private static int removeListener(Object listener) {
        int key = getListenerKey(listener);
        if (key == INVALID_KEY) return key;
        synchronized (sListenerMapLock) {
            sListenerMap.remove(key);
            return key;
        }
    }

    private static class ServiceHandler extends Handler {
        ServiceHandler(Looper looper) {
            super(looper);
        }
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
                    if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
                        sAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
                    } else {
                        Log.e(TAG, "Failed to set up channel connection");
                        // This will cause all further async API calls on the WifiManager
                        // to fail and throw an exception
                        sAsyncChannel = null;
                    }
                    sConnected.countDown();
                    return;
                case AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED:
                    return;
                case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
                    Log.e(TAG, "Channel connection lost");
                    // This will cause all further async API calls on the WifiManager
                    // to fail and throw an exception
                    sAsyncChannel = null;
                    getLooper().quit();
                    return;
            }

            Object listener = getListener(msg.arg2);
            if (listener == null) {
                if (DBG) Log.d(TAG, "invalid listener key = " + msg.arg2);
                return;
            } else {
                if (DBG) Log.d(TAG, "listener key = " + msg.arg2);
            }

            switch (msg.what) {
                /* ActionListeners grouped together */
                case CMD_OP_SUCCEEDED :
                    ((RttListener) listener).onSuccess((RttResult[])msg.obj);
                    break;
                case CMD_OP_FAILED :
                    ((RttListener) listener).onFailure(msg.arg1, (String)msg.obj);
                    removeListener(msg.arg2);
                    break;
                case CMD_OP_ABORTED :
                    ((RttListener) listener).onAborted();
                    removeListener(msg.arg2);
                    break;
                default:
                    if (DBG) Log.d(TAG, "Ignoring message " + msg.what);
                    return;
            }
        }
    }

}

