/*
 * 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.cts.verifier.wifiaware.testcase;

import static com.android.cts.verifier.wifiaware.CallbackUtils.CALLBACK_TIMEOUT_SEC;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.wifi.aware.PeerHandle;
import android.net.wifi.aware.PublishConfig;
import android.net.wifi.aware.PublishDiscoverySession;
import android.net.wifi.aware.SubscribeConfig;
import android.net.wifi.aware.SubscribeDiscoverySession;
import android.net.wifi.aware.WifiAwareManager;
import android.net.wifi.aware.WifiAwareSession;
import android.util.Log;
import android.util.Pair;

import com.android.cts.verifier.R;
import com.android.cts.verifier.wifiaware.BaseTestCase;
import com.android.cts.verifier.wifiaware.CallbackUtils;

/**
 *Test case for data-path, out-of-band (OOB) test cases:
 * open/passphrase * responder/initiator.
 *
 * OOB assumes that there's an alternative channel over which to communicate the discovery MAC
 * address of the Aware interface. That channel (e.g. bluetooth or a host test device) is not
 * readily available (don't want to have Aware tests dependent on BLE). Instead will fake the OOB
 * channel using Aware itself: will do normal discovery during which the devices will exchange their
 * MAC addresses, then destroy the discovery sessions and use the MAC addresses to perform OOB data-
 * path requests.
 *
 * Responder test sequence:
 * 1. Attach (with identity listener)
 *    wait for results (session)
 *    wait for identity
 * 2. Publish
 *    wait for results (publish session)
 * 3. Wait for rx message (with MAC)
 * 4. Send message with MAC
 *    wait for success
 * 5. Destroy discovery session
 * 6. Request network (as Responder)
 *    wait for network
 *
 * Initiator test sequence:
 * 1. Attach (with identity listener)
 *    wait for results (session)
 *    wait for identity
 * 2. Subscribe
 *    wait for results (subscribe session)
 * 3. Wait for discovery
 * 4. Send message with MAC
 *    wait for success
 * 5. Wait for rx message (with MAC)
 * 6. Destroy discovery session
 * 7. Sleep for 5 seconds to let Responder time to set up
 * 8. Request network (as Initiator)
 *    wait for network
 */
public class DataPathOutOfBandTestCase extends BaseTestCase {
    private static final String TAG = "DataPathOutOfBandTestCase";
    private static final boolean DBG = true;

    private static final int MAC_BYTES_LEN = 6;

    private static final String SERVICE_NAME = "CtsVerifierTestService";
    private static final String PASSPHRASE = "Some super secret password";
    private static final int MESSAGE_ID = 1234;

    private boolean mIsSecurityOpen;
    private boolean mIsResponder;

    private final Object mLock = new Object();

    private String mFailureReason;
    private WifiAwareSession mWifiAwareSession;
    private byte[] mDiscoveryMac;

    public DataPathOutOfBandTestCase(Context context, boolean isSecurityOpen,
            boolean isResponder) {
        super(context);
        mIsSecurityOpen = isSecurityOpen;
        mIsResponder = isResponder;
    }

    @Override
    protected boolean executeTest() throws InterruptedException {
        if (DBG) {
            Log.d(TAG, "executeTest: mIsSecurityOpen=" + mIsSecurityOpen + ", mIsResponder="
                    + mIsResponder);
        }

        // 1. attach (with identity listener)
        CallbackUtils.AttachCb attachCb = new CallbackUtils.AttachCb();
        CallbackUtils.IdentityListenerSingleShot identityL = new CallbackUtils
                .IdentityListenerSingleShot();
        mWifiAwareManager.attach(attachCb, identityL, mHandler);
        Pair<Integer, WifiAwareSession> results = attachCb.waitForAttach();
        switch (results.first) {
            case CallbackUtils.AttachCb.TIMEOUT:
                setFailureReason(mContext.getString(R.string.aware_status_attach_timeout));
                Log.e(TAG, "executeTest: attach TIMEOUT");
                return false;
            case CallbackUtils.AttachCb.ON_ATTACH_FAILED:
                setFailureReason(mContext.getString(R.string.aware_status_attach_fail));
                Log.e(TAG, "executeTest: attach ON_ATTACH_FAILED");
                return false;
        }
        mWifiAwareSession = results.second;
        if (mWifiAwareSession == null) {
            setFailureReason(mContext.getString(R.string.aware_status_attach_fail));
            Log.e(TAG, "executeTest: attach callback succeeded but null session returned!?");
            return false;
        }
        mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_attached));
        if (DBG) {
            Log.d(TAG, "executeTest: attach succeeded");
        }
        mDiscoveryMac = identityL.waitForMac();
        if (mDiscoveryMac == null) {
            setFailureReason(mContext.getString(R.string.aware_status_identity_fail));
            Log.e(TAG, "executeTest: identity callback not triggered");
            return false;
        }
        mListener.onTestMsgReceived(mResources.getString(R.string.aware_status_identity,
                bytesToHex(mDiscoveryMac, ':')));
        if (DBG) {
            Log.d(TAG, "executeTest: identity received: " + bytesToHex(mDiscoveryMac, ':'));
        }

        if (mIsResponder) {
            return executeTestResponder();
        } else {
            return executeTestInitiator();
        }
    }

    private void setFailureReason(String reason) {
        synchronized (mLock) {
            mFailureReason = reason;
        }
    }

    @Override
    protected String getFailureReason() {
        synchronized (mLock) {
            return mFailureReason;
        }
    }

    @Override
    protected void tearDown() {
        if (mWifiAwareSession != null) {
            mWifiAwareSession.close();
            mWifiAwareSession = null;
        }
        super.tearDown();
    }

    private boolean executeTestResponder() throws InterruptedException {
        if (DBG) Log.d(TAG, "executeTestResponder");
        CallbackUtils.DiscoveryCb discoveryCb = new CallbackUtils.DiscoveryCb();

        // 2. publish
        PublishConfig publishConfig = new PublishConfig.Builder().setServiceName(
                SERVICE_NAME).build();
        if (DBG) Log.d(TAG, "executeTestResponder: publishConfig=" + publishConfig);
        mWifiAwareSession.publish(publishConfig, discoveryCb, mHandler);

        //    wait for results - publish session
        CallbackUtils.DiscoveryCb.CallbackData callbackData = discoveryCb.waitForCallbacks(
                CallbackUtils.DiscoveryCb.ON_PUBLISH_STARTED
                        | CallbackUtils.DiscoveryCb.ON_SESSION_CONFIG_FAILED);
        switch (callbackData.callback) {
            case CallbackUtils.DiscoveryCb.TIMEOUT:
                setFailureReason(mContext.getString(R.string.aware_status_publish_timeout));
                Log.e(TAG, "executeTestResponder: publish TIMEOUT");
                return false;
            case CallbackUtils.DiscoveryCb.ON_SESSION_CONFIG_FAILED:
                setFailureReason(mContext.getString(R.string.aware_status_publish_failed));
                Log.e(TAG, "executeTestResponder: publish ON_SESSION_CONFIG_FAILED");
                return false;
        }
        PublishDiscoverySession discoverySession = callbackData.publishDiscoverySession;
        if (discoverySession == null) {
            setFailureReason(mContext.getString(R.string.aware_status_publish_null_session));
            Log.e(TAG, "executeTestResponder: publish succeeded but null session returned");
            return false;
        }
        mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_publish_started));
        if (DBG) Log.d(TAG, "executeTestResponder: publish succeeded");

        // 3. Wait for rx message (with MAC)
        callbackData = discoveryCb.waitForCallbacks(CallbackUtils.DiscoveryCb.ON_MESSAGE_RECEIVED);
        switch (callbackData.callback) {
            case CallbackUtils.DiscoveryCb.TIMEOUT:
                setFailureReason(mContext.getString(R.string.aware_status_receive_timeout));
                Log.e(TAG, "executeTestResponder: receive message TIMEOUT");
                return false;
        }

        if (callbackData.serviceSpecificInfo == null
                || callbackData.serviceSpecificInfo.length != MAC_BYTES_LEN) {
            setFailureReason(mContext.getString(R.string.aware_status_receive_failure));
            Log.e(TAG, "executeTestResponder: receive message message content mismatch: "
                    + bytesToHex(callbackData.serviceSpecificInfo, ':'));
            return false;
        }

        PeerHandle peerHandle = callbackData.peerHandle;
        byte[] peerMac = callbackData.serviceSpecificInfo;

        mListener.onTestMsgReceived(mResources.getString(R.string.aware_status_received_mac,
                bytesToHex(peerMac, ':')));
        if (DBG) {
            Log.d(TAG, "executeTestResponder: received MAC address: " + bytesToHex(peerMac, ':'));
        }

        // 4. Send message with MAC and wait for success
        discoverySession.sendMessage(peerHandle, MESSAGE_ID, mDiscoveryMac);
        callbackData = discoveryCb.waitForCallbacks(
                CallbackUtils.DiscoveryCb.ON_MESSAGE_SEND_SUCCEEDED
                        | CallbackUtils.DiscoveryCb.ON_MESSAGE_SEND_FAILED);
        switch (callbackData.callback) {
            case CallbackUtils.DiscoveryCb.TIMEOUT:
                setFailureReason(mContext.getString(R.string.aware_status_send_timeout));
                Log.e(TAG, "executeTestResponder: send message TIMEOUT");
                return false;
            case CallbackUtils.DiscoveryCb.ON_MESSAGE_SEND_FAILED:
                setFailureReason(mContext.getString(R.string.aware_status_send_failed));
                Log.e(TAG, "executeTestResponder: send message ON_MESSAGE_SEND_FAILED");
                return false;
        }
        mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_send_success));
        if (DBG) Log.d(TAG, "executeTestResponder: send message succeeded");

        if (callbackData.messageId != MESSAGE_ID) {
            setFailureReason(mContext.getString(R.string.aware_status_send_fail_parameter));
            Log.e(TAG, "executeTestResponder: send message message ID mismatch: "
                    + callbackData.messageId);
            return false;
        }

        // 5. Destroy discovery session
        discoverySession.close();

        // 6. Request network (as Responder) and wait for network
        ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(
                Context.CONNECTIVITY_SERVICE);
        NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
                NetworkCapabilities.TRANSPORT_WIFI_AWARE).setNetworkSpecifier(
                mIsSecurityOpen ? mWifiAwareSession.createNetworkSpecifierOpen(
                        WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER, peerMac)
                        : mWifiAwareSession.createNetworkSpecifierPassphrase(
                                WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER, peerMac,
                                PASSPHRASE)).build();
        CallbackUtils.NetworkCb networkCb = new CallbackUtils.NetworkCb();
        cm.requestNetwork(nr, CALLBACK_TIMEOUT_SEC * 1000, networkCb);
        mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_network_requested));
        if (DBG) Log.d(TAG, "executeTestResponder: requested network");
        boolean networkAvailable = networkCb.waitForNetwork();
        cm.unregisterNetworkCallback(networkCb);
        if (!networkAvailable) {
            setFailureReason(mContext.getString(R.string.aware_status_network_failed));
            Log.e(TAG, "executeTestResponder: network request rejected - ON_UNAVAILABLE");
            return false;
        }
        mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_network_success));
        if (DBG) Log.d(TAG, "executeTestResponder: network request granted - AVAILABLE");

        mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_lifecycle_ok));
        return true;
    }

    private boolean executeTestInitiator() throws InterruptedException {
        if (DBG) Log.d(TAG, "executeTestInitiator");
        CallbackUtils.DiscoveryCb discoveryCb = new CallbackUtils.DiscoveryCb();

        // 2. Subscribe
        SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().setServiceName(
                SERVICE_NAME).build();
        if (DBG) Log.d(TAG, "executeTestInitiator: subscribeConfig=" + subscribeConfig);
        mWifiAwareSession.subscribe(subscribeConfig, discoveryCb, mHandler);

        //    wait for results - subscribe session
        CallbackUtils.DiscoveryCb.CallbackData callbackData = discoveryCb.waitForCallbacks(
                CallbackUtils.DiscoveryCb.ON_SUBSCRIBE_STARTED
                        | CallbackUtils.DiscoveryCb.ON_SESSION_CONFIG_FAILED);
        switch (callbackData.callback) {
            case CallbackUtils.DiscoveryCb.TIMEOUT:
                setFailureReason(mContext.getString(R.string.aware_status_subscribe_timeout));
                Log.e(TAG, "executeTestInitiator: subscribe TIMEOUT");
                return false;
            case CallbackUtils.DiscoveryCb.ON_SESSION_CONFIG_FAILED:
                setFailureReason(mContext.getString(R.string.aware_status_subscribe_failed));
                Log.e(TAG, "executeTestInitiator: subscribe ON_SESSION_CONFIG_FAILED");
                return false;
        }
        SubscribeDiscoverySession discoverySession = callbackData.subscribeDiscoverySession;
        if (discoverySession == null) {
            setFailureReason(mContext.getString(R.string.aware_status_subscribe_null_session));
            Log.e(TAG, "executeTestInitiator: subscribe succeeded but null session returned");
            return false;
        }
        mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_subscribe_started));
        if (DBG) Log.d(TAG, "executeTestInitiator: subscribe succeeded");

        // 3. Wait for discovery
        callbackData = discoveryCb.waitForCallbacks(
                CallbackUtils.DiscoveryCb.ON_SERVICE_DISCOVERED);
        switch (callbackData.callback) {
            case CallbackUtils.DiscoveryCb.TIMEOUT:
                setFailureReason(mContext.getString(R.string.aware_status_discovery_timeout));
                Log.e(TAG, "executeTestInitiator: waiting for discovery TIMEOUT");
                return false;
        }
        PeerHandle peerHandle = callbackData.peerHandle;
        mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_discovery));
        if (DBG) Log.d(TAG, "executeTestInitiator: discovery");

        // 4. Send message with MAC and wait for success
        discoverySession.sendMessage(peerHandle, MESSAGE_ID, mDiscoveryMac);
        callbackData = discoveryCb.waitForCallbacks(
                CallbackUtils.DiscoveryCb.ON_MESSAGE_SEND_SUCCEEDED
                        | CallbackUtils.DiscoveryCb.ON_MESSAGE_SEND_FAILED);
        switch (callbackData.callback) {
            case CallbackUtils.DiscoveryCb.TIMEOUT:
                setFailureReason(mContext.getString(R.string.aware_status_send_timeout));
                Log.e(TAG, "executeTestInitiator: send message TIMEOUT");
                return false;
            case CallbackUtils.DiscoveryCb.ON_MESSAGE_SEND_FAILED:
                setFailureReason(mContext.getString(R.string.aware_status_send_failed));
                Log.e(TAG, "executeTestInitiator: send message ON_MESSAGE_SEND_FAILED");
                return false;
        }
        mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_send_success));
        if (DBG) Log.d(TAG, "executeTestInitiator: send message succeeded");

        if (callbackData.messageId != MESSAGE_ID) {
            setFailureReason(mContext.getString(R.string.aware_status_send_fail_parameter));
            Log.e(TAG, "executeTestInitiator: send message message ID mismatch: "
                    + callbackData.messageId);
            return false;
        }

        // 5. Wait for rx message (with MAC)
        callbackData = discoveryCb.waitForCallbacks(CallbackUtils.DiscoveryCb.ON_MESSAGE_RECEIVED);
        switch (callbackData.callback) {
            case CallbackUtils.DiscoveryCb.TIMEOUT:
                setFailureReason(mContext.getString(R.string.aware_status_receive_timeout));
                Log.e(TAG, "executeTestInitiator: receive message TIMEOUT");
                return false;
        }

        if (callbackData.serviceSpecificInfo == null
                || callbackData.serviceSpecificInfo.length != MAC_BYTES_LEN) {
            setFailureReason(mContext.getString(R.string.aware_status_receive_failure));
            Log.e(TAG, "executeTestInitiator: receive message message content mismatch: "
                    + bytesToHex(callbackData.serviceSpecificInfo, ':'));
            return false;
        }

        byte[] peerMac = callbackData.serviceSpecificInfo;

        mListener.onTestMsgReceived(mResources.getString(R.string.aware_status_received_mac,
                bytesToHex(peerMac, ':')));
        if (DBG) {
            Log.d(TAG, "executeTestInitiator: received MAC address: " + bytesToHex(peerMac, ':'));
        }

        // 6. Destroy discovery session
        discoverySession.close();

        // 7. Sleep for 5 seconds to let Responder time to set up
        mListener.onTestMsgReceived(
                mContext.getString(R.string.aware_status_sleeping_wait_for_responder));
        Thread.sleep(5000);

        // 8. Request network (as Initiator) and wait for network
        ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(
                Context.CONNECTIVITY_SERVICE);
        NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
                NetworkCapabilities.TRANSPORT_WIFI_AWARE).setNetworkSpecifier(
                mIsSecurityOpen ? mWifiAwareSession.createNetworkSpecifierOpen(
                        WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR, peerMac)
                        : mWifiAwareSession.createNetworkSpecifierPassphrase(
                                WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR, peerMac,
                                PASSPHRASE)).build();
        CallbackUtils.NetworkCb networkCb = new CallbackUtils.NetworkCb();
        cm.requestNetwork(nr, CALLBACK_TIMEOUT_SEC * 1000, networkCb);
        mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_network_requested));
        if (DBG) Log.d(TAG, "executeTestInitiator: requested network");
        boolean networkAvailable = networkCb.waitForNetwork();
        cm.unregisterNetworkCallback(networkCb);
        if (!networkAvailable) {
            setFailureReason(mContext.getString(R.string.aware_status_network_failed));
            Log.e(TAG, "executeTestInitiator: network request rejected - ON_UNAVAILABLE");
            return false;
        }
        mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_network_success));
        if (DBG) Log.d(TAG, "executeTestInitiator: network request granted - AVAILABLE");

        mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_lifecycle_ok));
        return true;
    }
}
