/*
 * 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.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;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Test case for data-path, in-band test cases:
 * open/passphrase * solicited/unsolicited * publish/subscribe.
 *
 * Subscribe test sequence:
 * 1. Attach
 *    wait for results (session)
 * 2. Subscribe
 *    wait for results (subscribe session)
 * 3. Wait for discovery
 * 4. Send message
 *    Wait for success
 * 5. Wait for rx message
 * 6. Request network
 *    Wait for network
 * 7. Destroy session
 *
 * Publish test sequence:
 * 1. Attach
 *    wait for results (session)
 * 2. Publish
 *    wait for results (publish session)
 * 3. Wait for rx message
 * 4. Request network
 * 5. Send message
 *    Wait for success
 * 6. Wait for network
 * 7. Destroy session
 */
public class DataPathInBandTestCase extends BaseTestCase {
    private static final String TAG = "DataPathInBandTestCase";
    private static final boolean DBG = true;

    private static final String SERVICE_NAME = "CtsVerifierTestService";
    private static final byte[] MATCH_FILTER_BYTES = "bytes used for matching".getBytes();
    private static final byte[] PUB_SSI = "Extra bytes in the publisher discovery".getBytes();
    private static final byte[] SUB_SSI = "Arbitrary bytes for the subscribe discovery".getBytes();
    private static final byte[] MSG_SUB_TO_PUB = "Let's talk".getBytes();
    private static final byte[] MSG_PUB_TO_SUB = "Ready".getBytes();
    private static final String PASSPHRASE = "Some super secret password";
    private static final int MESSAGE_ID = 1234;

    private boolean mIsSecurityOpen;
    private boolean mIsPublish;
    private boolean mIsUnsolicited;

    private final Object mLock = new Object();

    private String mFailureReason;
    private WifiAwareSession mWifiAwareSession;

    public DataPathInBandTestCase(Context context, boolean isSecurityOpen, boolean isPublish,
            boolean isUnsolicited) {
        super(context);
        mIsSecurityOpen = isSecurityOpen;
        mIsPublish = isPublish;
        mIsUnsolicited = isUnsolicited;
    }

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

        // 1. attach
        CallbackUtils.AttachCb attachCb = new CallbackUtils.AttachCb();
        mWifiAwareManager.attach(attachCb, 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");
        }

        if (mIsPublish) {
            return executeTestPublisher();
        } else {
            return executeTestSubscriber();
        }
    }

    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 executeTestSubscriber() throws InterruptedException {
        if (DBG) Log.d(TAG, "executeTestSubscriber");
        CallbackUtils.DiscoveryCb discoveryCb = new CallbackUtils.DiscoveryCb();

        // 2. subscribe
        List<byte[]> matchFilter = new ArrayList<>();
        matchFilter.add(MATCH_FILTER_BYTES);
        SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().setServiceName(
                SERVICE_NAME).setServiceSpecificInfo(SUB_SSI).setMatchFilter(
                matchFilter).setSubscribeType(
                mIsUnsolicited ? SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE
                        : SubscribeConfig.SUBSCRIBE_TYPE_ACTIVE).setTerminateNotificationEnabled(
                true).build();
        if (DBG) Log.d(TAG, "executeTestSubscriber: 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, "executeTestSubscriber: subscribe TIMEOUT");
                return false;
            case CallbackUtils.DiscoveryCb.ON_SESSION_CONFIG_FAILED:
                setFailureReason(mContext.getString(R.string.aware_status_subscribe_failed));
                Log.e(TAG, "executeTestSubscriber: 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, "executeTestSubscriber: subscribe succeeded but null session returned");
            return false;
        }
        mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_subscribe_started));
        if (DBG) Log.d(TAG, "executeTestSubscriber: 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, "executeTestSubscriber: waiting for discovery TIMEOUT");
                return false;
        }
        PeerHandle peerHandle = callbackData.peerHandle;
        mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_discovery));
        if (DBG) Log.d(TAG, "executeTestSubscriber: discovery");

        //    validate discovery parameters match
        if (!Arrays.equals(PUB_SSI, callbackData.serviceSpecificInfo)) {
            setFailureReason(mContext.getString(R.string.aware_status_discovery_fail));
            Log.e(TAG, "executeTestSubscriber: discovery but SSI mismatch: rx='" + new String(
                    callbackData.serviceSpecificInfo) + "'");
            return false;
        }
        if (callbackData.matchFilter.size() != 1 || !Arrays.equals(MATCH_FILTER_BYTES,
                callbackData.matchFilter.get(0))) {
            setFailureReason(mContext.getString(R.string.aware_status_discovery_fail));
            StringBuffer sb = new StringBuffer();
            sb.append("size=").append(callbackData.matchFilter.size());
            for (byte[] mf: callbackData.matchFilter) {
                sb.append(", e='").append(new String(mf)).append("'");
            }
            Log.e(TAG, "executeTestSubscriber: discovery but matchFilter mismatch: "
                    + sb.toString());
            return false;
        }
        if (peerHandle == null) {
            setFailureReason(mContext.getString(R.string.aware_status_discovery_fail));
            Log.e(TAG, "executeTestSubscriber: discovery but null peerHandle");
            return false;
        }

        // 4. send message & wait for send status
        discoverySession.sendMessage(peerHandle, MESSAGE_ID, MSG_SUB_TO_PUB);
        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, "executeTestSubscriber: send message TIMEOUT");
                return false;
            case CallbackUtils.DiscoveryCb.ON_MESSAGE_SEND_FAILED:
                setFailureReason(mContext.getString(R.string.aware_status_send_failed));
                Log.e(TAG, "executeTestSubscriber: send message ON_MESSAGE_SEND_FAILED");
                return false;
        }
        mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_send_success));
        if (DBG) Log.d(TAG, "executeTestSubscriber: send message succeeded");

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

        // 5. wait to receive message
        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, "executeTestSubscriber: receive message TIMEOUT");
                return false;
        }
        mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_received));
        if (DBG) Log.d(TAG, "executeTestSubscriber: received message");

        //    validate that received the expected message
        if (!Arrays.equals(MSG_PUB_TO_SUB, callbackData.serviceSpecificInfo)) {
            setFailureReason(mContext.getString(R.string.aware_status_receive_failure));
            Log.e(TAG, "executeTestSubscriber: receive message message content mismatch: rx='"
                    + new String(callbackData.serviceSpecificInfo) + "'");
            return false;
        }

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

        // 7. destroy session
        discoverySession.close();

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

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

        // 2. publish
        List<byte[]> matchFilter = new ArrayList<>();
        matchFilter.add(MATCH_FILTER_BYTES);
        PublishConfig publishConfig = new PublishConfig.Builder().setServiceName(
                SERVICE_NAME).setServiceSpecificInfo(PUB_SSI).setMatchFilter(
                matchFilter).setPublishType(mIsUnsolicited ? PublishConfig.PUBLISH_TYPE_UNSOLICITED
                : PublishConfig.PUBLISH_TYPE_SOLICITED).setTerminateNotificationEnabled(
                true).build();
        if (DBG) Log.d(TAG, "executeTestPublisher: 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, "executeTestPublisher: publish TIMEOUT");
                return false;
            case CallbackUtils.DiscoveryCb.ON_SESSION_CONFIG_FAILED:
                setFailureReason(mContext.getString(R.string.aware_status_publish_failed));
                Log.e(TAG, "executeTestPublisher: 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, "executeTestPublisher: publish succeeded but null session returned");
            return false;
        }
        mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_publish_started));
        if (DBG) Log.d(TAG, "executeTestPublisher: publish succeeded");

        // 3. wait to receive message: no timeout since this depends on (human) operator starting
        //    the test on the subscriber device.
        callbackData = discoveryCb.waitForCallbacksNoTimeout(
                CallbackUtils.DiscoveryCb.ON_MESSAGE_RECEIVED);
        PeerHandle peerHandle = callbackData.peerHandle;
        mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_received));
        if (DBG) Log.d(TAG, "executeTestPublisher: received message");

        //    validate that received the expected message
        if (!Arrays.equals(MSG_SUB_TO_PUB, callbackData.serviceSpecificInfo)) {
            setFailureReason(mContext.getString(R.string.aware_status_receive_failure));
            Log.e(TAG, "executeTestPublisher: receive message message content mismatch: rx='"
                    + new String(callbackData.serviceSpecificInfo) + "'");
            return false;
        }
        if (peerHandle == null) {
            setFailureReason(mContext.getString(R.string.aware_status_receive_failure));
            Log.e(TAG, "executeTestPublisher: received message but peerHandle is null!?");
            return false;
        }

        // 4. Request network
        ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(
                Context.CONNECTIVITY_SERVICE);
        NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
                NetworkCapabilities.TRANSPORT_WIFI_AWARE).setNetworkSpecifier(
                mIsSecurityOpen ? discoverySession.createNetworkSpecifierOpen(peerHandle)
                        : discoverySession.createNetworkSpecifierPassphrase(peerHandle,
                                PASSPHRASE)).build();
        CallbackUtils.NetworkCb networkCb = new CallbackUtils.NetworkCb();
        cm.requestNetwork(nr, networkCb, CALLBACK_TIMEOUT_SEC * 1000);
        mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_network_requested));
        if (DBG) Log.d(TAG, "executeTestPublisher: requested network");

        // 5. send message & wait for send status
        discoverySession.sendMessage(peerHandle, MESSAGE_ID, MSG_PUB_TO_SUB);
        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, "executeTestPublisher: send message TIMEOUT");
                return false;
            case CallbackUtils.DiscoveryCb.ON_MESSAGE_SEND_FAILED:
                setFailureReason(mContext.getString(R.string.aware_status_send_failed));
                Log.e(TAG, "executeTestPublisher: send message ON_MESSAGE_SEND_FAILED");
                return false;
        }
        mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_send_success));
        if (DBG) Log.d(TAG, "executeTestPublisher: send message succeeded");

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

        // 6. wait for network
        boolean networkAvailable = networkCb.waitForNetwork();
        cm.unregisterNetworkCallback(networkCb);
        if (!networkAvailable) {
            setFailureReason(mContext.getString(R.string.aware_status_network_failed));
            Log.e(TAG, "executeTestPublisher: request network rejected - ON_UNAVAILABLE");
            return false;
        }
        mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_network_success));
        if (DBG) Log.d(TAG, "executeTestPublisher: network request granted - AVAILABLE");

        // 7. destroy session
        discoverySession.close();

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

    }
}
