/*
 * Copyright (C) 2018 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.internal.telephony.dataconnection;

import android.content.Context;
import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
import android.telephony.Rlog;
import android.telephony.data.ApnSetting;
import android.telephony.data.ApnSetting.ApnType;
import android.util.Log;

import com.android.internal.telephony.Phone;
import com.android.internal.telephony.uicc.IccRecords;

import java.util.Arrays;
import java.util.HashSet;

/**
 * This class represents a apn setting for create PDP link
 */
public class ApnSettingUtils {

    static final String LOG_TAG = "ApnSetting";

    private static final boolean DBG = false;

    private static boolean iccidMatches(String mvnoData, String iccId) {
        String[] mvnoIccidList = mvnoData.split(",");
        for (String mvnoIccid : mvnoIccidList) {
            if (iccId.startsWith(mvnoIccid)) {
                Log.d(LOG_TAG, "mvno icc id match found");
                return true;
            }
        }
        return false;
    }

    private static boolean imsiMatches(String imsiDB, String imsiSIM) {
        // Note: imsiDB value has digit number or 'x' character for seperating USIM information
        // for MVNO operator. And then digit number is matched at same order and 'x' character
        // could replace by any digit number.
        // ex) if imsiDB inserted '310260x10xxxxxx' for GG Operator,
        //     that means first 6 digits, 8th and 9th digit
        //     should be set in USIM for GG Operator.
        int len = imsiDB.length();

        if (len <= 0) return false;
        if (len > imsiSIM.length()) return false;

        for (int idx = 0; idx < len; idx++) {
            char c = imsiDB.charAt(idx);
            if ((c == 'x') || (c == 'X') || (c == imsiSIM.charAt(idx))) {
                continue;
            } else {
                return false;
            }
        }
        return true;
    }

    /**
     * Check if MVNO type and data match IccRecords.
     *
     * @param r the IccRecords
     * @param mvnoType the MVNO type
     * @param mvnoMatchData the MVNO match data
     * @return {@code true} if MVNO type and data match IccRecords, {@code false} otherwise.
     */
    public static boolean mvnoMatches(IccRecords r, int mvnoType, String mvnoMatchData) {
        if (mvnoType == ApnSetting.MVNO_TYPE_SPN) {
            if ((r.getServiceProviderName() != null)
                    && r.getServiceProviderName().equalsIgnoreCase(mvnoMatchData)) {
                return true;
            }
        } else if (mvnoType == ApnSetting.MVNO_TYPE_IMSI) {
            String imsiSIM = r.getIMSI();
            if ((imsiSIM != null) && imsiMatches(mvnoMatchData, imsiSIM)) {
                return true;
            }
        } else if (mvnoType == ApnSetting.MVNO_TYPE_GID) {
            String gid1 = r.getGid1();
            int mvno_match_data_length = mvnoMatchData.length();
            if ((gid1 != null) && (gid1.length() >= mvno_match_data_length)
                    && gid1.substring(0, mvno_match_data_length).equalsIgnoreCase(mvnoMatchData)) {
                return true;
            }
        } else if (mvnoType == ApnSetting.MVNO_TYPE_ICCID) {
            String iccId = r.getIccId();
            if ((iccId != null) && iccidMatches(mvnoMatchData, iccId)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Check if this APN type is metered.
     *
     * @param apnType the APN type
     * @param phone the phone object
     * @return {@code true} if the APN type is metered, {@code false} otherwise.
     */
    public static boolean isMeteredApnType(@ApnType int apnType, Phone phone) {
        if (phone == null) {
            return true;
        }

        boolean isRoaming = phone.getServiceState().getDataRoaming();
        int subId = phone.getSubId();

        String carrierConfig;
        // First check if the device is roaming. If yes, use the roaming metered APN list.
        // Otherwise use the normal metered APN list.
        if (isRoaming) {
            carrierConfig = CarrierConfigManager.KEY_CARRIER_METERED_ROAMING_APN_TYPES_STRINGS;
        } else {
            carrierConfig = CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS;
        }

        if (DBG) {
            Rlog.d(LOG_TAG, "isMeteredApnType: isRoaming=" + isRoaming);
        }

        CarrierConfigManager configManager = (CarrierConfigManager)
                phone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
        if (configManager == null) {
            Rlog.e(LOG_TAG, "Carrier config service is not available");
            return true;
        }

        PersistableBundle b = configManager.getConfigForSubId(subId);
        if (b == null) {
            Rlog.e(LOG_TAG, "Can't get the config. subId = " + subId);
            return true;
        }

        String[] meteredApnTypes = b.getStringArray(carrierConfig);
        if (meteredApnTypes == null) {
            Rlog.e(LOG_TAG, carrierConfig +  " is not available. " + "subId = " + subId);
            return true;
        }

        HashSet<String> meteredApnSet = new HashSet<>(Arrays.asList(meteredApnTypes));
        if (DBG) {
            Rlog.d(LOG_TAG, "For subId = " + subId + ", metered APN types are "
                    + Arrays.toString(meteredApnSet.toArray()));
        }

        if (meteredApnSet.contains(ApnSetting.getApnTypeString(apnType))) {
            if (DBG) Rlog.d(LOG_TAG, ApnSetting.getApnTypeString(apnType) + " is metered.");
            return true;
        } else if (apnType == ApnSetting.TYPE_ALL) {
            // Assuming no configuration error, if at least one APN type is
            // metered, then this APN setting is metered.
            if (meteredApnSet.size() > 0) {
                if (DBG) Rlog.d(LOG_TAG, "APN_TYPE_ALL APN is metered.");
                return true;
            }
        }

        if (DBG) Rlog.d(LOG_TAG, ApnSetting.getApnTypeString(apnType) + " is not metered.");
        return false;
    }

    /**
     * Check if this APN setting is metered.
     *
     * @param apn APN setting
     * @param phone The phone object
     * @return True if this APN setting is metered, otherwise false.
     */
    public static boolean isMetered(ApnSetting apn, Phone phone) {
        if (phone == null || apn == null) {
            return true;
        }

        for (int apnType : apn.getApnTypes()) {
            // If one of the APN type is metered, then this APN setting is metered.
            if (isMeteredApnType(apnType, phone)) {
                return true;
            }
        }
        return false;
    }
}
