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

import static android.content.Context.TELEPHONY_SERVICE;
import static android.net.ConnectivityManager.TYPE_ETHERNET;
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_MOBILE_DUN;
import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI;
import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;

import android.content.Context;
import android.content.res.Resources;
import android.net.TetheringConfigurationParcel;
import android.net.util.SharedLog;
import android.provider.DeviceConfig;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;

import com.android.internal.annotations.VisibleForTesting;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.StringJoiner;


/**
 * A utility class to encapsulate the various tethering configuration elements.
 *
 * This configuration data includes elements describing upstream properties
 * (preferred and required types of upstream connectivity as well as default
 * DNS servers to use if none are available) and downstream properties (such
 * as regular expressions use to match suitable downstream interfaces and the
 * DHCPv4 ranges to use).
 *
 * @hide
 */
public class TetheringConfiguration {
    private static final String TAG = TetheringConfiguration.class.getSimpleName();

    private static final String[] EMPTY_STRING_ARRAY = new String[0];

    // Default ranges used for the legacy DHCP server.
    // USB is  192.168.42.1 and 255.255.255.0
    // Wifi is 192.168.43.1 and 255.255.255.0
    // BT is limited to max default of 5 connections. 192.168.44.1 to 192.168.48.1
    // with 255.255.255.0
    // P2P is 192.168.49.1 and 255.255.255.0
    private static final String[] LEGACY_DHCP_DEFAULT_RANGE = {
        "192.168.42.2", "192.168.42.254", "192.168.43.2", "192.168.43.254",
        "192.168.44.2", "192.168.44.254", "192.168.45.2", "192.168.45.254",
        "192.168.46.2", "192.168.46.254", "192.168.47.2", "192.168.47.254",
        "192.168.48.2", "192.168.48.254", "192.168.49.2", "192.168.49.254",
    };

    private static final String[] DEFAULT_IPV4_DNS = {"8.8.4.4", "8.8.8.8"};

    /**
     * Override enabling BPF offload configuration for tethering.
     */
    public static final String OVERRIDE_TETHER_ENABLE_BPF_OFFLOAD =
            "override_tether_enable_bpf_offload";

    /**
     * Use the old dnsmasq DHCP server for tethering instead of the framework implementation.
     */
    public static final String TETHER_ENABLE_LEGACY_DHCP_SERVER =
            "tether_enable_legacy_dhcp_server";

    /**
     * Default value that used to periodic polls tether offload stats from tethering offload HAL
     * to make the data warnings work.
     */
    public static final int DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS = 5000;

    public final String[] tetherableUsbRegexs;
    public final String[] tetherableWifiRegexs;
    public final String[] tetherableWigigRegexs;
    public final String[] tetherableWifiP2pRegexs;
    public final String[] tetherableBluetoothRegexs;
    public final String[] tetherableNcmRegexs;
    public final boolean isDunRequired;
    public final boolean chooseUpstreamAutomatically;
    public final Collection<Integer> preferredUpstreamIfaceTypes;
    public final String[] legacyDhcpRanges;
    public final String[] defaultIPv4DNS;
    public final boolean enableLegacyDhcpServer;

    public final String[] provisioningApp;
    public final String provisioningAppNoUi;
    public final int provisioningCheckPeriod;
    public final String provisioningResponse;

    public final int activeDataSubId;

    private final int mOffloadPollInterval;
    // TODO: Add to TetheringConfigurationParcel if required.
    private final boolean mEnableBpfOffload;

    public TetheringConfiguration(Context ctx, SharedLog log, int id) {
        final SharedLog configLog = log.forSubComponent("config");

        activeDataSubId = id;
        Resources res = getResources(ctx, activeDataSubId);

        tetherableUsbRegexs = getResourceStringArray(res, R.array.config_tether_usb_regexs);
        tetherableNcmRegexs = getResourceStringArray(res, R.array.config_tether_ncm_regexs);
        // TODO: Evaluate deleting this altogether now that Wi-Fi always passes
        // us an interface name. Careful consideration needs to be given to
        // implications for Settings and for provisioning checks.
        tetherableWifiRegexs = getResourceStringArray(res, R.array.config_tether_wifi_regexs);
        tetherableWigigRegexs = getResourceStringArray(res, R.array.config_tether_wigig_regexs);
        tetherableWifiP2pRegexs = getResourceStringArray(
                res, R.array.config_tether_wifi_p2p_regexs);
        tetherableBluetoothRegexs = getResourceStringArray(
                res, R.array.config_tether_bluetooth_regexs);

        isDunRequired = checkDunRequired(ctx);

        chooseUpstreamAutomatically = getResourceBoolean(
                res, R.bool.config_tether_upstream_automatic, false /** defaultValue */);
        preferredUpstreamIfaceTypes = getUpstreamIfaceTypes(res, isDunRequired);

        legacyDhcpRanges = getLegacyDhcpRanges(res);
        defaultIPv4DNS = copy(DEFAULT_IPV4_DNS);
        mEnableBpfOffload = getEnableBpfOffload(res);
        enableLegacyDhcpServer = getEnableLegacyDhcpServer(res);

        provisioningApp = getResourceStringArray(res, R.array.config_mobile_hotspot_provision_app);
        provisioningAppNoUi = getResourceString(res,
                R.string.config_mobile_hotspot_provision_app_no_ui);
        provisioningCheckPeriod = getResourceInteger(res,
                R.integer.config_mobile_hotspot_provision_check_period,
                0 /* No periodic re-check */);
        provisioningResponse = getResourceString(res,
                R.string.config_mobile_hotspot_provision_response);

        mOffloadPollInterval = getResourceInteger(res,
                R.integer.config_tether_offload_poll_interval,
                DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS);

        configLog.log(toString());
    }

    /** Check whether input interface belong to usb.*/
    public boolean isUsb(String iface) {
        return matchesDownstreamRegexs(iface, tetherableUsbRegexs);
    }

    /** Check whether input interface belong to wifi.*/
    public boolean isWifi(String iface) {
        return matchesDownstreamRegexs(iface, tetherableWifiRegexs);
    }

    /** Check whether input interface belong to wigig.*/
    public boolean isWigig(String iface) {
        return matchesDownstreamRegexs(iface, tetherableWigigRegexs);
    }

    /** Check whether this interface is Wifi P2P interface. */
    public boolean isWifiP2p(String iface) {
        return matchesDownstreamRegexs(iface, tetherableWifiP2pRegexs);
    }

    /** Check whether using legacy mode for wifi P2P. */
    public boolean isWifiP2pLegacyTetheringMode() {
        return (tetherableWifiP2pRegexs == null || tetherableWifiP2pRegexs.length == 0);
    }

    /** Check whether input interface belong to bluetooth.*/
    public boolean isBluetooth(String iface) {
        return matchesDownstreamRegexs(iface, tetherableBluetoothRegexs);
    }

    /** Check if interface is ncm */
    public boolean isNcm(String iface) {
        return matchesDownstreamRegexs(iface, tetherableNcmRegexs);
    }

    /** Check whether no ui entitlement application is available.*/
    public boolean hasMobileHotspotProvisionApp() {
        return !TextUtils.isEmpty(provisioningAppNoUi);
    }

    /** Does the dumping.*/
    public void dump(PrintWriter pw) {
        pw.print("activeDataSubId: ");
        pw.println(activeDataSubId);

        dumpStringArray(pw, "tetherableUsbRegexs", tetherableUsbRegexs);
        dumpStringArray(pw, "tetherableWifiRegexs", tetherableWifiRegexs);
        dumpStringArray(pw, "tetherableWifiP2pRegexs", tetherableWifiP2pRegexs);
        dumpStringArray(pw, "tetherableBluetoothRegexs", tetherableBluetoothRegexs);
        dumpStringArray(pw, "tetherableNcmRegexs", tetherableNcmRegexs);

        pw.print("isDunRequired: ");
        pw.println(isDunRequired);

        pw.print("chooseUpstreamAutomatically: ");
        pw.println(chooseUpstreamAutomatically);
        pw.print("legacyPreredUpstreamIfaceTypes: ");
        pw.println(Arrays.toString(toIntArray(preferredUpstreamIfaceTypes)));

        dumpStringArray(pw, "legacyDhcpRanges", legacyDhcpRanges);
        dumpStringArray(pw, "defaultIPv4DNS", defaultIPv4DNS);

        pw.print("offloadPollInterval: ");
        pw.println(mOffloadPollInterval);

        dumpStringArray(pw, "provisioningApp", provisioningApp);
        pw.print("provisioningAppNoUi: ");
        pw.println(provisioningAppNoUi);

        pw.print("enableBpfOffload: ");
        pw.println(mEnableBpfOffload);

        pw.print("enableLegacyDhcpServer: ");
        pw.println(enableLegacyDhcpServer);
    }

    /** Returns the string representation of this object.*/
    public String toString() {
        final StringJoiner sj = new StringJoiner(" ");
        sj.add(String.format("activeDataSubId:%d", activeDataSubId));
        sj.add(String.format("tetherableUsbRegexs:%s", makeString(tetherableUsbRegexs)));
        sj.add(String.format("tetherableWifiRegexs:%s", makeString(tetherableWifiRegexs)));
        sj.add(String.format("tetherableWifiP2pRegexs:%s", makeString(tetherableWifiP2pRegexs)));
        sj.add(String.format("tetherableBluetoothRegexs:%s",
                makeString(tetherableBluetoothRegexs)));
        sj.add(String.format("isDunRequired:%s", isDunRequired));
        sj.add(String.format("chooseUpstreamAutomatically:%s", chooseUpstreamAutomatically));
        sj.add(String.format("offloadPollInterval:%d", mOffloadPollInterval));
        sj.add(String.format("preferredUpstreamIfaceTypes:%s",
                toIntArray(preferredUpstreamIfaceTypes)));
        sj.add(String.format("provisioningApp:%s", makeString(provisioningApp)));
        sj.add(String.format("provisioningAppNoUi:%s", provisioningAppNoUi));
        sj.add(String.format("enableBpfOffload:%s", mEnableBpfOffload));
        sj.add(String.format("enableLegacyDhcpServer:%s", enableLegacyDhcpServer));
        return String.format("TetheringConfiguration{%s}", sj.toString());
    }

    private static void dumpStringArray(PrintWriter pw, String label, String[] values) {
        pw.print(label);
        pw.print(": ");

        if (values != null) {
            final StringJoiner sj = new StringJoiner(", ", "[", "]");
            for (String value : values) sj.add(value);
            pw.print(sj.toString());
        } else {
            pw.print("null");
        }

        pw.println();
    }

    private static String makeString(String[] strings) {
        if (strings == null) return "null";
        final StringJoiner sj = new StringJoiner(",", "[", "]");
        for (String s : strings) sj.add(s);
        return sj.toString();
    }

    /** Check whether dun is required. */
    public static boolean checkDunRequired(Context ctx) {
        final TelephonyManager tm = (TelephonyManager) ctx.getSystemService(TELEPHONY_SERVICE);
        // TelephonyManager would uses the active data subscription, which should be the one used
        // by tethering.
        return (tm != null) ? tm.isTetheringApnRequired() : false;
    }

    public int getOffloadPollInterval() {
        return mOffloadPollInterval;
    }

    public boolean isBpfOffloadEnabled() {
        return mEnableBpfOffload;
    }

    private static Collection<Integer> getUpstreamIfaceTypes(Resources res, boolean dunRequired) {
        final int[] ifaceTypes = res.getIntArray(R.array.config_tether_upstream_types);
        final ArrayList<Integer> upstreamIfaceTypes = new ArrayList<>(ifaceTypes.length);
        for (int i : ifaceTypes) {
            switch (i) {
                case TYPE_MOBILE:
                case TYPE_MOBILE_HIPRI:
                    if (dunRequired) continue;
                    break;
                case TYPE_MOBILE_DUN:
                    if (!dunRequired) continue;
                    break;
            }
            upstreamIfaceTypes.add(i);
        }

        // Fix up upstream interface types for DUN or mobile. NOTE: independent
        // of the value of |dunRequired|, cell data of one form or another is
        // *always* an upstream, regardless of the upstream interface types
        // specified by configuration resources.
        if (dunRequired) {
            appendIfNotPresent(upstreamIfaceTypes, TYPE_MOBILE_DUN);
        } else {
            // Do not modify if a cellular interface type is already present in the
            // upstream interface types. Add TYPE_MOBILE and TYPE_MOBILE_HIPRI if no
            // cellular interface types are found in the upstream interface types.
            // This preserves backwards compatibility and prevents the DUN and default
            // mobile types incorrectly appearing together, which could happen on
            // previous releases in the common case where checkDunRequired returned
            // DUN_UNSPECIFIED.
            if (!containsOneOf(upstreamIfaceTypes, TYPE_MOBILE, TYPE_MOBILE_HIPRI)) {
                upstreamIfaceTypes.add(TYPE_MOBILE);
                upstreamIfaceTypes.add(TYPE_MOBILE_HIPRI);
            }
        }

        // Always make sure our good friend Ethernet is present.
        // TODO: consider unilaterally forcing this at the front.
        prependIfNotPresent(upstreamIfaceTypes, TYPE_ETHERNET);

        return upstreamIfaceTypes;
    }

    private static boolean matchesDownstreamRegexs(String iface, String[] regexs) {
        for (String regex : regexs) {
            if (iface.matches(regex)) return true;
        }
        return false;
    }

    private static String[] getLegacyDhcpRanges(Resources res) {
        final String[] fromResource = getResourceStringArray(res, R.array.config_tether_dhcp_range);
        if ((fromResource.length > 0) && (fromResource.length % 2 == 0)) {
            return fromResource;
        }
        return copy(LEGACY_DHCP_DEFAULT_RANGE);
    }

    private static String getResourceString(Resources res, final int resId) {
        try {
            return res.getString(resId);
        } catch (Resources.NotFoundException e) {
            return "";
        }
    }

    private static boolean getResourceBoolean(Resources res, int resId, boolean defaultValue) {
        try {
            return res.getBoolean(resId);
        } catch (Resources.NotFoundException e404) {
            return defaultValue;
        }
    }

    private static String[] getResourceStringArray(Resources res, int resId) {
        try {
            final String[] strArray = res.getStringArray(resId);
            return (strArray != null) ? strArray : EMPTY_STRING_ARRAY;
        } catch (Resources.NotFoundException e404) {
            return EMPTY_STRING_ARRAY;
        }
    }

    private static int getResourceInteger(Resources res, int resId, int defaultValue) {
        try {
            return res.getInteger(resId);
        } catch (Resources.NotFoundException e404) {
            return defaultValue;
        }
    }

    private boolean getEnableBpfOffload(final Resources res) {
        // Get BPF offload config
        // Priority 1: Device config
        // Priority 2: Resource config
        // Priority 3: Default value
        final boolean defaultValue = getResourceBoolean(
                res, R.bool.config_tether_enable_bpf_offload, true /** default value */);

        return getDeviceConfigBoolean(OVERRIDE_TETHER_ENABLE_BPF_OFFLOAD, defaultValue);
    }

    private boolean getEnableLegacyDhcpServer(final Resources res) {
        return getResourceBoolean(
                res, R.bool.config_tether_enable_legacy_dhcp_server, false /** defaultValue */)
                || getDeviceConfigBoolean(
                TETHER_ENABLE_LEGACY_DHCP_SERVER, false /** defaultValue */);
    }

    private boolean getDeviceConfigBoolean(final String name, final boolean defaultValue) {
        // Due to the limitation of static mock for testing, using #getDeviceConfigProperty instead
        // of DeviceConfig#getBoolean. If using #getBoolean here, the test can't know that the
        // returned boolean value comes from device config or default value (because of null
        // property string). See the test case testBpfOffload{*} in TetheringConfigurationTest.java.
        final String value = getDeviceConfigProperty(name);
        return value != null ? Boolean.parseBoolean(value) : defaultValue;
    }

    @VisibleForTesting
    protected String getDeviceConfigProperty(String name) {
        return DeviceConfig.getProperty(NAMESPACE_CONNECTIVITY, name);
    }

    private Resources getResources(Context ctx, int subId) {
        if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
            return getResourcesForSubIdWrapper(ctx, subId);
        } else {
            return ctx.getResources();
        }
    }

    @VisibleForTesting
    protected Resources getResourcesForSubIdWrapper(Context ctx, int subId) {
        return SubscriptionManager.getResourcesForSubId(ctx, subId);
    }

    private static String[] copy(String[] strarray) {
        return Arrays.copyOf(strarray, strarray.length);
    }

    private static void prependIfNotPresent(ArrayList<Integer> list, int value) {
        if (list.contains(value)) return;
        list.add(0, value);
    }

    private static void appendIfNotPresent(ArrayList<Integer> list, int value) {
        if (list.contains(value)) return;
        list.add(value);
    }

    private static boolean containsOneOf(ArrayList<Integer> list, Integer... values) {
        for (Integer value : values) {
            if (list.contains(value)) return true;
        }
        return false;
    }

    private static int[] toIntArray(Collection<Integer> values) {
        final int[] result = new int[values.size()];
        int index = 0;
        for (Integer value : values) {
            result[index++] = value;
        }
        return result;
    }

    /**
     * Convert this TetheringConfiguration to a TetheringConfigurationParcel.
     */
    public TetheringConfigurationParcel toStableParcelable() {
        final TetheringConfigurationParcel parcel = new TetheringConfigurationParcel();
        parcel.subId = activeDataSubId;
        parcel.tetherableUsbRegexs = tetherableUsbRegexs;
        parcel.tetherableWifiRegexs = tetherableWifiRegexs;
        parcel.tetherableBluetoothRegexs = tetherableBluetoothRegexs;
        parcel.isDunRequired = isDunRequired;
        parcel.chooseUpstreamAutomatically = chooseUpstreamAutomatically;

        parcel.preferredUpstreamIfaceTypes = toIntArray(preferredUpstreamIfaceTypes);

        parcel.legacyDhcpRanges = legacyDhcpRanges;
        parcel.defaultIPv4DNS = defaultIPv4DNS;
        parcel.enableLegacyDhcpServer = enableLegacyDhcpServer;
        parcel.provisioningApp = provisioningApp;
        parcel.provisioningAppNoUi = provisioningAppNoUi;
        parcel.provisioningCheckPeriod = provisioningCheckPeriod;
        return parcel;
    }
}
