/*
 * Copyright (C) 2015 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 android.net.cts.legacy.api22;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkInfo;
import android.net.wifi.WifiManager;
import android.os.ConditionVariable;
import android.test.AndroidTestCase;
import android.util.Log;

import java.net.DatagramSocket;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;

import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI;
import static android.net.ConnectivityManager.TYPE_VPN;
import static android.net.ConnectivityManager.TYPE_WIFI;

public class ConnectivityManagerLegacyTest extends AndroidTestCase {
    private static final String TAG = ConnectivityManagerLegacyTest.class.getSimpleName();
    private static final String FEATURE_ENABLE_HIPRI = "enableHIPRI";
    private static final String HOST_ADDRESS1 = "192.0.2.1";
    private static final String HOST_ADDRESS2 = "192.0.2.2";
    private static final String HOST_ADDRESS3 = "192.0.2.3";

    // These are correct as of API level 22, which is what we target here.
    private static final int APN_REQUEST_FAILED = 3;
    private static final int MAX_NETWORK_TYPE = TYPE_VPN;

    private ConnectivityManager mCm;
    private WifiManager mWifiManager;
    private PackageManager mPackageManager;

    private final List<Integer>mProtectedNetworks = new ArrayList<Integer>();

    protected void setUp() throws Exception {
        super.setUp();
        mCm = (ConnectivityManager) getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
        mWifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
        mPackageManager = getContext().getPackageManager();

        // Get com.android.internal.R.array.config_protectedNetworks
        int resId = getContext().getResources().getIdentifier("config_protectedNetworks", "array", "android");
        int[] protectedNetworks = getContext().getResources().getIntArray(resId);
        for (int p : protectedNetworks) {
            mProtectedNetworks.add(p);
        }
    }

    // true if only the system can turn it on
    private boolean isNetworkProtected(int networkType) {
        return mProtectedNetworks.contains(networkType);
    }

    private int ipv4AddrToInt(String addrString) throws Exception {
        byte[] addr = ((Inet4Address) InetAddress.getByName(addrString)).getAddress();
        return ((addr[3] & 0xff) << 24) | ((addr[2] & 0xff) << 16) |
                ((addr[1] & 0xff) << 8) | (addr[0] & 0xff);
    }

    private void checkSourceAddress(String addrString, int type) throws Exception {
        DatagramSocket d = new DatagramSocket();
        d.connect(InetAddress.getByName(addrString), 7);
        InetAddress localAddress = d.getLocalAddress();

        Network[] networks = mCm.getAllNetworks();
        for (int i = 0; i < networks.length; i++) {
            NetworkInfo ni = mCm.getNetworkInfo(networks[i]);
            if (ni != null && ni.getType() == type) {
                LinkProperties lp = mCm.getLinkProperties(networks[i]);
                for (LinkAddress address : lp.getLinkAddresses()) {
                    if (address.getAddress().equals(localAddress)) {
                        return;
                    }
                }
            }
        }
        fail("Local address " + localAddress + " not assigned to any network of type " + type);
    }

    /** Test that hipri can be brought up when Wifi is enabled. */
    public void testStartUsingNetworkFeature_enableHipri() throws Exception {
        if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)
                || !mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI)) {
            // This test requires a mobile data connection and WiFi.
            return;
        }

        // Make sure WiFi is connected to an access point.
        connectToWifi();

        expectNetworkBroadcast(TYPE_MOBILE_HIPRI, NetworkInfo.State.CONNECTED,
                new Runnable() {
                    public void run() {
                        int ret = mCm.startUsingNetworkFeature(TYPE_MOBILE, FEATURE_ENABLE_HIPRI);
                        assertTrue("Couldn't start using the HIPRI feature.", ret != -1);
                    }
                });

        assertTrue("Couldn't requestRouteToHost using HIPRI.",
                mCm.requestRouteToHost(TYPE_MOBILE_HIPRI, ipv4AddrToInt(HOST_ADDRESS1)));

        try { Thread.sleep(1000); } catch(Exception e) {}
        checkSourceAddress(HOST_ADDRESS1, TYPE_MOBILE);
        checkSourceAddress(HOST_ADDRESS2, TYPE_WIFI);

        // TODO check dns selection

        expectNetworkBroadcast(TYPE_MOBILE_HIPRI, NetworkInfo.State.DISCONNECTED,
                new Runnable() {
                    public void run() {
                        int ret = mCm.stopUsingNetworkFeature(TYPE_MOBILE, FEATURE_ENABLE_HIPRI);
                        assertTrue("Couldn't stop using the HIPRI feature.", ret != -1);
                    }
                });


        // TODO check dns selection
        disconnectFromWifi();
    }

    public void testStartUsingNetworkFeature() {

        final String invalidFeature = "invalidFeature";
        final String mmsFeature = "enableMMS";
        final int failureCode = -1;
        final int wifiOnlyStartFailureCode = APN_REQUEST_FAILED;
        final int wifiOnlyStopFailureCode = -1;

        NetworkInfo ni = mCm.getNetworkInfo(TYPE_MOBILE);
        if (ni != null) {
            assertEquals(APN_REQUEST_FAILED,
                    mCm.startUsingNetworkFeature(TYPE_MOBILE, invalidFeature));
            assertEquals(failureCode, mCm.stopUsingNetworkFeature(TYPE_MOBILE, invalidFeature));
        } else {
            assertEquals(wifiOnlyStartFailureCode, mCm.startUsingNetworkFeature(TYPE_MOBILE,
                    invalidFeature));
            assertEquals(wifiOnlyStopFailureCode, mCm.stopUsingNetworkFeature(TYPE_MOBILE,
                    invalidFeature));
        }

        ni = mCm.getNetworkInfo(TYPE_WIFI);
        if (ni != null) {
            // Should return failure because MMS is not supported on WIFI.
            assertEquals(APN_REQUEST_FAILED, mCm.startUsingNetworkFeature(TYPE_WIFI,
                    mmsFeature));
            assertEquals(failureCode, mCm.stopUsingNetworkFeature(TYPE_WIFI,
                    mmsFeature));
        }
    }

    private void expectNetworkBroadcast(final int type, final NetworkInfo.State state,
            Runnable afterWhat) {
        final int TIMEOUT_MS = 30 * 1000;
        final ConditionVariable var = new ConditionVariable();

        Log.d(TAG, "Waiting for " + state + " broadcast for type " + type);
        BroadcastReceiver receiver = new BroadcastReceiver() {
            public void onReceive(Context context, Intent intent) {
                NetworkInfo ni = intent.getExtras()
                        .getParcelable(ConnectivityManager.EXTRA_NETWORK_INFO);
                assertNotNull("CONNECTIVITY_ACTION with null EXTRA_NETWORK_INFO", ni);
                if (ni.getType() == type && ni.getState().equals(state)) {
                    Log.d(TAG, "Received expected " + state + " broadcast for type " + type);
                    var.open();
                }
            }
        };
        IntentFilter filter = new IntentFilter();
        filter.addAction(CONNECTIVITY_ACTION);
        mContext.registerReceiver(receiver, filter);

        try {
            afterWhat.run();
            final String msg = "Did not receive expected " + state + " broadcast for type " + type +
                    " after " + TIMEOUT_MS + " ms";
            assertTrue(msg, var.block(TIMEOUT_MS));
        } finally {
            mContext.unregisterReceiver(receiver);
        }
    }

    private boolean isWifiConnected() {
        NetworkInfo ni = mCm.getNetworkInfo(TYPE_WIFI);
        return ni != null && ni.isConnected();
    }

    private void setWifiState(final boolean enabled) {
        if (enabled != isWifiConnected()) {
            final NetworkInfo.State desiredState = enabled ?
                    NetworkInfo.State.CONNECTED :
                    NetworkInfo.State.DISCONNECTED;
            expectNetworkBroadcast(TYPE_WIFI, desiredState, new Runnable() {
                public void run() {
                    mWifiManager.setWifiEnabled(enabled);
                }
            });
        }
    }

    private void connectToWifi() {
        setWifiState(true);
    }

    private void disconnectFromWifi() {
        setWifiState(false);
    }

    private boolean isNetworkSupported(int networkType) {
        return mCm.getNetworkInfo(networkType) != null;
    }

    public void testRequestRouteToHost() throws Exception {
        for (int type = -1 ; type <= MAX_NETWORK_TYPE; type++) {
            NetworkInfo ni = mCm.getNetworkInfo(type);
            boolean expectToWork = isNetworkSupported(type) && !isNetworkProtected(type) &&
                    ni != null && ni.isConnected();

            try {
                assertTrue("Network type " + type,
                        mCm.requestRouteToHost(type, ipv4AddrToInt(HOST_ADDRESS3)) == expectToWork);
            } catch (Exception e) {
                Log.d(TAG, "got exception in requestRouteToHost for type " + type);
                assertFalse("Exception received for type " + type, expectToWork);
            }

            //TODO verify route table
        }

        assertFalse(mCm.requestRouteToHost(-1, ipv4AddrToInt(HOST_ADDRESS1)));
    }
}
