/*
 * Copyright (C) 2020 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.wifi.cts;

import static android.net.wifi.WifiConfiguration.METERED_OVERRIDE_NONE;

import android.net.Uri;
import android.net.wifi.hotspot2.OsuProvider;
import android.net.wifi.hotspot2.PasspointConfiguration;
import android.net.wifi.hotspot2.pps.Credential;
import android.net.wifi.hotspot2.pps.HomeSp;
import android.text.TextUtils;

import java.lang.reflect.Constructor;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

public class WifiHotspot2Test extends WifiJUnit3TestBase {
    static final int SIM_CREDENTIAL = 0;
    static final int USER_CREDENTIAL = 1;
    static final int CERT_CREDENTIAL = 2;
    private static final String TEST_SSID = "TEST SSID";
    private static final String TEST_FRIENDLY_NAME = "Friendly Name";
    private static final Map<String, String> TEST_FRIENDLY_NAMES =
            new HashMap<String, String>() {
                {
                    put("en", TEST_FRIENDLY_NAME);
                    put("kr", TEST_FRIENDLY_NAME + 2);
                    put("jp", TEST_FRIENDLY_NAME + 3);
                }
            };
    private static final String TEST_SERVICE_DESCRIPTION = "Dummy Service";
    private static final Uri TEST_SERVER_URI = Uri.parse("https://test.com");
    private static final String TEST_NAI = "test.access.com";
    private static final List<Integer> TEST_METHOD_LIST =
            Arrays.asList(1 /* METHOD_SOAP_XML_SPP */);
    private static final long SUBSCRIPTION_EXPIRATION_TIME_MS = 1643996661000L;

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        if (!WifiFeature.isWifiSupported(getContext())) {
            // skip the test if WiFi is not supported
            return;
        }
    }

    @Override
    protected void tearDown() throws Exception {
        super.tearDown();
    }

    /**
     * Tests {@link PasspointConfiguration#getMeteredOverride()} method.
     * <p>
     * Test default value
     */
    public void testGetMeteredOverride() throws Exception {
        if (!WifiFeature.isWifiSupported(getContext())) {
            // skip the test if WiFi is not supported
            return;
        }
        PasspointConfiguration passpointConfiguration = new PasspointConfiguration();
        assertEquals(METERED_OVERRIDE_NONE, passpointConfiguration.getMeteredOverride());
    }

    /**
     * Tests {@link PasspointConfiguration#getSubscriptionExpirationTimeMillis()} and
     * {@link PasspointConfiguration#setSubscriptionExpirationTimeInMillis(long)}
     * <p>
     */
    public void testGetSetSubscriptionExpirationTimeMillis() throws Exception {
        if (!WifiFeature.isWifiSupported(getContext())) {
            // skip the test if WiFi is not supported
            return;
        }
        PasspointConfiguration passpointConfiguration = new PasspointConfiguration();
        assertEquals(Long.MIN_VALUE,
                passpointConfiguration.getSubscriptionExpirationTimeMillis());
        passpointConfiguration
                .setSubscriptionExpirationTimeInMillis(SUBSCRIPTION_EXPIRATION_TIME_MS);
        assertEquals(SUBSCRIPTION_EXPIRATION_TIME_MS,
                passpointConfiguration.getSubscriptionExpirationTimeMillis());
    }

    /**
     * Tests {@link PasspointConfiguration#getUniqueId()} method.
     * <p>
     * Test unique identifier is not null
     */
    public void testGetUniqueId() throws Exception {
        if (!WifiFeature.isWifiSupported(getContext())) {
            // skip the test if WiFi is not supported
            return;
        }

        // Create a configuration and make sure the unique ID is not null
        PasspointConfiguration passpointConfiguration1 = createConfig(SIM_CREDENTIAL, "123456*",
                18 /* EAP_SIM */);
        String uniqueId1 = passpointConfiguration1.getUniqueId();
        assertNotNull(uniqueId1);

        // Create another configuration and make sure the unique ID is not null
        PasspointConfiguration passpointConfiguration2 = createConfig(SIM_CREDENTIAL, "567890*",
                23 /* EAP_AKA */);
        String uniqueId2 = passpointConfiguration2.getUniqueId();
        assertNotNull(uniqueId2);

        // Make sure the IDs are not equal
        assertFalse(uniqueId1.equals(uniqueId2));

        passpointConfiguration2 = createConfig(USER_CREDENTIAL);
        assertFalse(uniqueId1.equals(passpointConfiguration2.getUniqueId()));

        passpointConfiguration2 = createConfig(CERT_CREDENTIAL);
        assertFalse(uniqueId1.equals(passpointConfiguration2.getUniqueId()));
    }

    /**
     * Tests {@link PasspointConfiguration#isAutojoinEnabled()} method.
     * <p>
     * Test default value
     */
    public void testIsAutojoinEnabled() throws Exception {
        if (!WifiFeature.isWifiSupported(getContext())) {
            // skip the test if WiFi is not supported
            return;
        }
        PasspointConfiguration passpointConfiguration = new PasspointConfiguration();
        assertTrue(passpointConfiguration.isAutojoinEnabled());
    }

    /**
     * Tests {@link PasspointConfiguration#isMacRandomizationEnabled()} method.
     * <p>
     * Test default value
     */
    public void testIsMacRandomizationEnabled() throws Exception {
        if (!WifiFeature.isWifiSupported(getContext())) {
            // skip the test if WiFi is not supported
            return;
        }
        PasspointConfiguration passpointConfiguration = new PasspointConfiguration();
        assertTrue(passpointConfiguration.isMacRandomizationEnabled());
    }

    /**
     * Tests {@link PasspointConfiguration#isOsuProvisioned()} method.
     * <p>
     * Test default value
     */
    public void testIsOsuProvisioned() throws Exception {
        if (!WifiFeature.isWifiSupported(getContext())) {
            // skip the test if WiFi is not supported
            return;
        }
        PasspointConfiguration passpointConfiguration = createConfig(USER_CREDENTIAL);
        assertFalse(passpointConfiguration.isOsuProvisioned());
    }

    /**
     * Tests {@link PasspointConfiguration#PasspointConfiguration(PasspointConfiguration)} method.
     * <p>
     * Test the PasspointConfiguration copy constructor
     */
    public void testPasspointConfigurationCopyConstructor() throws Exception {
        if (!WifiFeature.isWifiSupported(getContext())) {
            // skip the test if WiFi is not supported
            return;
        }
        PasspointConfiguration passpointConfiguration = createConfig(USER_CREDENTIAL);
        PasspointConfiguration copyOfPasspointConfiguration =
                new PasspointConfiguration(passpointConfiguration);
        assertEquals(passpointConfiguration, copyOfPasspointConfiguration);
    }

    /**
     * Tests {@link HomeSp#HomeSp(HomeSp)} method.
     * <p>
     * Test the HomeSp copy constructor
     */
    public void testHomeSpCopyConstructor() throws Exception {
        if (!WifiFeature.isWifiSupported(getContext())) {
            // skip the test if WiFi is not supported
            return;
        }
        HomeSp homeSp = createHomeSp();
        HomeSp copyOfHomeSp = new HomeSp(homeSp);
        assertEquals(copyOfHomeSp, homeSp);
    }

    /**
     * Tests {@link Credential#Credential(Credential)} method.
     * <p>
     * Test the Credential copy constructor
     */
    public void testCredentialCopyConstructor() throws Exception {
        if (!WifiFeature.isWifiSupported(getContext())) {
            // skip the test if WiFi is not supported
            return;
        }
        Credential credential = createCredentialWithSimCredential("123456*", 18 /* EAP_SIM */);
        Credential copyOfCredential = new Credential(credential);
        assertEquals(copyOfCredential, credential);
    }

    /**
     * Tests {@link Credential.UserCredential#UserCredential(Credential.UserCredential)} method.
     * <p>
     * Test the Credential.UserCredential copy constructor
     */
    public void testUserCredentialCopyConstructor() throws Exception {
        if (!WifiFeature.isWifiSupported(getContext())) {
            // skip the test if WiFi is not supported
            return;
        }
        Credential.UserCredential userCredential = new Credential.UserCredential();
        userCredential.setUsername("username");
        userCredential.setPassword("password");
        userCredential.setEapType(21 /* EAP_TTLS */);
        userCredential.setNonEapInnerMethod("MS-CHAP");

        Credential.UserCredential copyOfUserCredential =
                new Credential.UserCredential(userCredential);
        assertEquals(copyOfUserCredential, userCredential);
    }

    /**
     * Tests
     * {@link Credential.CertificateCredential#CertificateCredential(Credential.CertificateCredential)}
     * method.
     * <p>
     * Test the Credential.CertificateCredential copy constructor
     */
    public void testCertCredentialCopyConstructor() throws Exception {
        if (!WifiFeature.isWifiSupported(getContext())) {
            // skip the test if WiFi is not supported
            return;
        }
        Credential.CertificateCredential certCredential = new Credential.CertificateCredential();
        certCredential.setCertType("x509v3");

        Credential.CertificateCredential copyOfCertificateCredential =
                new Credential.CertificateCredential(certCredential);
        assertEquals(copyOfCertificateCredential, certCredential);
    }

    /**
     * Tests {@link Credential.SimCredential#SimCredential(Credential.SimCredential)} method.
     * <p>
     * Test the Credential.SimCredential copy constructor
     */
    public void testSimCredentialCopyConstructor() throws Exception {
        if (!WifiFeature.isWifiSupported(getContext())) {
            // skip the test if WiFi is not supported
            return;
        }
        Credential.SimCredential simCredential = new Credential.SimCredential();
        simCredential.setImsi("1234*");
        simCredential.setEapType(18/* EAP_SIM */);

        Credential.SimCredential copyOfSimCredential = new Credential.SimCredential(simCredential);
        assertEquals(copyOfSimCredential, simCredential);
    }

    /**
     * Tests {@link Credential#getCaCertificate()}  method.
     * <p>
     * Test that getting a set certificate produces the same value
     */
    public void testCredentialGetCertificate() throws Exception {
        if (!WifiFeature.isWifiSupported(getContext())) {
            // skip the test if WiFi is not supported
            return;
        }
        Credential credential = new Credential();
        credential.setCaCertificate(FakeKeys.CA_CERT0);

        assertEquals(FakeKeys.CA_CERT0, credential.getCaCertificate());
    }

    /**
     * Tests {@link Credential#getClientCertificateChain()} and {@link
     * Credential#setCaCertificates(X509Certificate[])} methods.
     * <p>
     * Test that getting a set client certificate chain produces the same value
     */
    public void testCredentialClientCertificateChain() throws Exception {
        if (!WifiFeature.isWifiSupported(getContext())) {
            // skip the test if WiFi is not supported
            return;
        }
        Credential credential = new Credential();
        X509Certificate[] certificates = new X509Certificate[]{FakeKeys.CLIENT_CERT};
        credential.setClientCertificateChain(certificates);

        assertTrue(Arrays.equals(certificates, credential.getClientCertificateChain()));
    }

    /**
     * Tests {@link Credential#getClientPrivateKey()} and
     * {@link Credential#setClientPrivateKey(PrivateKey)}
     * methods.
     * <p>
     * Test that getting a set client private key produces the same value
     */
    public void testCredentialSetGetClientPrivateKey() throws Exception {
        if (!WifiFeature.isWifiSupported(getContext())) {
            // skip the test if WiFi is not supported
            return;
        }
        Credential credential = new Credential();
        credential.setClientPrivateKey(FakeKeys.RSA_KEY1);

        assertEquals(FakeKeys.RSA_KEY1, credential.getClientPrivateKey());
    }

    /**
     * Tests {@link Credential#getClientPrivateKey()} and
     * {@link Credential#setClientPrivateKey(PrivateKey)}
     * methods.
     * <p>
     * Test that getting a set client private key produces the same value
     */
    public void testCredentialGetClientPrivateKey() throws Exception {
        if (!WifiFeature.isWifiSupported(getContext())) {
            // skip the test if WiFi is not supported
            return;
        }
        Credential credential = new Credential();
        credential.setClientPrivateKey(FakeKeys.RSA_KEY1);

        assertEquals(FakeKeys.RSA_KEY1, credential.getClientPrivateKey());
    }

    private static PasspointConfiguration createConfig(int type) throws Exception {
        return createConfig(type, "123456*", 18 /* EAP_SIM */);
    }

    private static PasspointConfiguration createConfig(int type, String imsi, int eapType)
            throws Exception {
        PasspointConfiguration config = new PasspointConfiguration();
        config.setHomeSp(createHomeSp());
        switch (type) {
            default:
            case SIM_CREDENTIAL:
                config.setCredential(
                        createCredentialWithSimCredential(imsi, eapType));
                break;
            case USER_CREDENTIAL:
                config.setCredential(createCredentialWithUserCredential());
                break;
            case CERT_CREDENTIAL:
                config.setCredential(createCredentialWithCertificateCredential());
                break;
        }

        return config;
    }

    /**
     * Helper function for generating HomeSp for testing.
     *
     * @return {@link HomeSp}
     */
    private static HomeSp createHomeSp() {
        HomeSp homeSp = new HomeSp();
        homeSp.setFqdn("test.com");
        homeSp.setFriendlyName("friendly name");
        homeSp.setRoamingConsortiumOis(new long[]{0x55, 0x66});
        return homeSp;
    }

    /**
     * Helper function for generating Credential for testing.
     *
     * @param userCred               Instance of UserCredential
     * @param certCred               Instance of CertificateCredential
     * @param simCred                Instance of SimCredential
     * @param clientCertificateChain Chain of client certificates
     * @param clientPrivateKey       Client private key
     * @param caCerts                CA certificates
     * @return {@link Credential}
     */
    private static Credential createCredential(Credential.UserCredential userCred,
            Credential.CertificateCredential certCred,
            Credential.SimCredential simCred,
            X509Certificate[] clientCertificateChain, PrivateKey clientPrivateKey,
            X509Certificate... caCerts) {
        Credential cred = new Credential();
        cred.setRealm("realm");
        cred.setUserCredential(userCred);
        cred.setCertCredential(certCred);
        cred.setSimCredential(simCred);
        return cred;
    }

    /**
     * Helper function for generating certificate credential for testing.
     *
     * @return {@link Credential}
     */
    private static Credential createCredentialWithCertificateCredential()
            throws NoSuchAlgorithmException, CertificateEncodingException {
        Credential.CertificateCredential certCred = new Credential.CertificateCredential();
        certCred.setCertType("x509v3");
        certCred.setCertSha256Fingerprint(
                MessageDigest.getInstance("SHA-256").digest(
                        FakeKeys.CLIENT_CERT.getEncoded()));
        return createCredential(null, certCred, null, new X509Certificate[]{
                        FakeKeys.CLIENT_CERT},
                FakeKeys.RSA_KEY1, FakeKeys.CA_CERT0,
                FakeKeys.CA_CERT1);
    }

    /**
     * Helper function for generating SIM credential for testing.
     *
     * @return {@link Credential}
     */
    private static Credential createCredentialWithSimCredential(String imsi, int eapType) {
        Credential.SimCredential simCred = new Credential.SimCredential();
        simCred.setImsi(imsi);
        simCred.setEapType(eapType);
        return createCredential(null, null, simCred, null, null, (X509Certificate[]) null);
    }

    /**
     * Helper function for generating user credential for testing.
     *
     * @return {@link Credential}
     */
    private static Credential createCredentialWithUserCredential() {
        Credential.UserCredential userCred = new Credential.UserCredential();
        userCred.setUsername("username");
        userCred.setPassword("password");
        userCred.setEapType(21 /* EAP_TTLS */);
        userCred.setNonEapInnerMethod("MS-CHAP");
        return createCredential(userCred, null, null, null, null,
                FakeKeys.CA_CERT0);
    }

    /**
     * Tests {@link OsuProvider#getFriendlyName()} and {@link OsuProvider#getServerUri()} methods.
     * <p>
     * Test that getting a set friendly name and server URI produces the same value
     */
    public void testOsuProviderGetters() throws Exception {
        if (!WifiFeature.isWifiSupported(getContext())) {
            // skip the test if WiFi is not supported
            return;
        }

        // Using Java reflection to construct an OsuProvider instance because its constructor is
        // hidden and not available to apps.
        Class<?> osuProviderClass = Class.forName("android.net.wifi.hotspot2.OsuProvider");
        Constructor<?> osuProviderClassConstructor = osuProviderClass.getConstructor(String.class,
                Map.class, String.class, Uri.class, String.class, List.class);

        OsuProvider osuProvider = (OsuProvider) osuProviderClassConstructor.newInstance(TEST_SSID,
                TEST_FRIENDLY_NAMES, TEST_SERVICE_DESCRIPTION, TEST_SERVER_URI, TEST_NAI,
                TEST_METHOD_LIST);
        String lang = Locale.getDefault().getLanguage();
        String friendlyName = TEST_FRIENDLY_NAMES.get(lang);
        if (TextUtils.isEmpty(friendlyName)) {
            friendlyName = TEST_FRIENDLY_NAMES.get("en");
        }
        assertEquals(friendlyName, osuProvider.getFriendlyName());
        assertEquals(TEST_SERVER_URI, osuProvider.getServerUri());
    }

}
