/*
 * Copyright 2019 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.annotation.IntDef;
import android.annotation.NonNull;
import android.telephony.data.ApnSetting;
import android.telephony.data.ApnSetting.ApnType;
import android.text.TextUtils;
import android.util.ArrayMap;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.SubscriptionController;
import com.android.internal.telephony.dataconnection.DataEnabledOverride.OverrideConditions.Condition;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * This class represents the rules for overriding data enabled settings in different conditions.
 * When data is disabled by the user, data can still be turned on temporarily when conditions
 * satisfy any rule here.
 */
public class DataEnabledOverride {

    private final Set<OverrideRule> mRules = new HashSet<>();

    /**
     * The rule for allowing data during voice call.
     */
    private static final OverrideRule OVERRIDE_RULE_ALLOW_DATA_DURING_VOICE_CALL =
            new OverrideRule(ApnSetting.TYPE_ALL, OverrideConditions.CONDITION_IN_VOICE_CALL
                    | OverrideConditions.CONDITION_NON_DEFAULT);

    /**
     * The rule for always allowing mms. Without adding any condition to the rule, any condition can
     * satisfy this rule for mms.
     */
    private static final OverrideRule OVERRIDE_RULE_ALWAYS_ALLOW_MMS =
            new OverrideRule(ApnSetting.TYPE_MMS, OverrideConditions.CONDITION_UNCONDITIONALLY);

    /**
     * Data enabled override rule
     */
    private static class OverrideRule {
        /**
         * APN type of the rule. The rule is APN type specific. The override is applicable to the
         * specified APN type as well. For now we only support one APN type per rule. Can be
         * expanded to multiple APN types in the future.
         */
        private final @ApnType int mApnType;

        /** The required conditions for overriding */
        private final OverrideConditions mRequiredConditions;

        /**
         * Constructor
         *
         * @param rule The override rule string. For example, {@code mms=nonDefault} or
         * {@code default=voiceCall & nonDefault}
         */
        OverrideRule(@NonNull String rule) {
            String[] tokens = rule.trim().split("\\s*=\\s*");
            if (tokens.length != 2) {
                throw new IllegalArgumentException("Invalid data enabled override rule format: "
                        + rule);
            }

            if (TextUtils.isEmpty(tokens[0])) {
                throw new IllegalArgumentException("APN type can't be empty");
            }

            mApnType = ApnSetting.getApnTypesBitmaskFromString(tokens[0]);
            if (mApnType == ApnSetting.TYPE_NONE) {
                throw new IllegalArgumentException("Invalid APN type. Rule=" + rule);
            }

            mRequiredConditions = new OverrideConditions(tokens[1]);
        }

        /**
         * Constructor
         *
         * @param apnType APN type of the rule
         * @param requiredConditions The required conditions for the rule
         */
        private OverrideRule(int apnType, int requiredConditions) {
            mApnType = apnType;
            mRequiredConditions = new OverrideConditions(requiredConditions);
        }

        /**
         * Check if this rule can be satisfied by the given APN type and provided conditions.
         *
         * @param apnType APN type to check
         * @param providedConditions The provided conditions to check
         * @return {@code true} if satisfied
         */
        boolean isSatisfiedByConditions(@ApnType int apnType, @Condition int providedConditions) {
            return (mApnType == apnType || mApnType == ApnSetting.TYPE_ALL)
                    && mRequiredConditions.allMet(providedConditions);
        }

        @Override
        public String toString() {
            return ApnSetting.getApnTypeString(mApnType) + "=" + mRequiredConditions;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            OverrideRule that = (OverrideRule) o;
            return mApnType == that.mApnType
                    && Objects.equals(mRequiredConditions, that.mRequiredConditions);
        }

        @Override
        public int hashCode() {
            return Objects.hash(mApnType, mRequiredConditions);
        }
    }

    /**
     * Represent the conditions for overriding data enabled settings
     */
    static class OverrideConditions {
        // Possible values for data enabled override condition. Note these flags are bitmasks.
        /** Unconditionally override enabled settings */
        static final int CONDITION_UNCONDITIONALLY = 0;

        /** Enable data only on subscription that is not user selected default data subscription */
        static final int CONDITION_NON_DEFAULT = 1 << 0;

        /** Enable data only when device has ongoing voice call */
        static final int CONDITION_IN_VOICE_CALL = 1 << 1;

        /** Enable data unconditionally in string format */
        static final String CONDITION_UNCONDITIONALLY_STRING = "unconditionally";

        /** Enable data only on subscription that is not default in string format */
        static final String CONDITION_NON_DEFAULT_STRING = "nonDefault";

        /** Enable data only when device has ongoing voice call in string format */
        static final String CONDITION_VOICE_CALL_STRING = "inVoiceCall";

        /** @hide */
        @IntDef(flag = true, prefix = { "OVERRIDE_CONDITION_" }, value = {
                CONDITION_NON_DEFAULT,
                CONDITION_IN_VOICE_CALL,
        })
        @Retention(RetentionPolicy.SOURCE)
        public @interface Condition {}

        private static final Map<Integer, String> OVERRIDE_CONDITION_INT_MAP = new ArrayMap<>();
        private static final Map<String, Integer> OVERRIDE_CONDITION_STRING_MAP = new ArrayMap<>();

        static {
            OVERRIDE_CONDITION_INT_MAP.put(CONDITION_NON_DEFAULT,
                    CONDITION_NON_DEFAULT_STRING);
            OVERRIDE_CONDITION_INT_MAP.put(CONDITION_IN_VOICE_CALL,
                    CONDITION_VOICE_CALL_STRING);

            OVERRIDE_CONDITION_STRING_MAP.put(CONDITION_UNCONDITIONALLY_STRING,
                    CONDITION_UNCONDITIONALLY);
            OVERRIDE_CONDITION_STRING_MAP.put(CONDITION_NON_DEFAULT_STRING,
                    CONDITION_NON_DEFAULT);
            OVERRIDE_CONDITION_STRING_MAP.put(CONDITION_VOICE_CALL_STRING,
                    CONDITION_IN_VOICE_CALL);
        }

        private final @Condition int mConditions;

        /**
         * Conditions for overriding data enabled setting
         *
         * @param conditions Conditions in string format
         */
        OverrideConditions(@NonNull String conditions) {
            mConditions = getBitmaskFromString(conditions);
        }

        /**
         * Conditions for overriding data enabled setting
         *
         * @param conditions Conditions in bitmask
         */
        OverrideConditions(@Condition int conditions) {
            mConditions = conditions;
        }

        private static String getStringFromBitmask(@Condition int conditions) {
            if (conditions == CONDITION_UNCONDITIONALLY) {
                return CONDITION_UNCONDITIONALLY_STRING;
            }
            List<String> conditionsStrings = new ArrayList<>();
            for (Integer condition : OVERRIDE_CONDITION_INT_MAP.keySet()) {
                if ((conditions & condition) == condition) {
                    conditionsStrings.add(OVERRIDE_CONDITION_INT_MAP.get(condition));
                }
            }
            return TextUtils.join("&", conditionsStrings);
        }

        private static @Condition int getBitmaskFromString(@NonNull String str) {
            if (TextUtils.isEmpty(str)) {
                throw new IllegalArgumentException("Empty rule string");
            }

            String[] conditionStrings = str.trim().split("\\s*&\\s*");
            int bitmask = 0;

            for (String conditionStr : conditionStrings) {
                if (!TextUtils.isEmpty(conditionStr)) {
                    if (!OVERRIDE_CONDITION_STRING_MAP.containsKey(conditionStr)) {
                        throw new IllegalArgumentException("Invalid conditions: " + str);
                    }
                    bitmask |= OVERRIDE_CONDITION_STRING_MAP.get(conditionStr);
                }
            }

            return bitmask;
        }

        /**
         * Check if provided conditions can meet all conditions in the rule.
         *
         * @param providedConditions The provided conditions
         * @return {@code true} if all conditions are met.
         */
        boolean allMet(@Condition int providedConditions) {
            return (providedConditions & mConditions) == mConditions;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            OverrideConditions that = (OverrideConditions) o;
            return mConditions == that.mConditions;
        }

        @Override
        public int hashCode() {
            return Objects.hash(mConditions);
        }

        @Override
        public String toString() {
            return getStringFromBitmask(mConditions);
        }
    }

    /**
     * Constructor
     *
     * @param rules Data enabled override rules
     */
    public DataEnabledOverride(@NonNull String rules) {
        updateRules(rules);
    }

    /**
     * Update the data enabled override rules.
     *
     * @param newRules New override rules
     */
    @VisibleForTesting
    public void updateRules(@NonNull String newRules) {
        mRules.clear();
        String[] rulesString = newRules.trim().split("\\s*,\\s*");
        for (String rule : rulesString) {
            if (!TextUtils.isEmpty(rule)) {
                mRules.add(new OverrideRule(rule));
            }
        }
    }

    /**
     * Set always allowing MMS
     *
     * @param allow {@code true} if always allowing, otherwise {@code false}.
     */
    public void setAlwaysAllowMms(boolean allow) {
        if (allow) {
            mRules.add(OVERRIDE_RULE_ALWAYS_ALLOW_MMS);
        } else {
            mRules.remove(OVERRIDE_RULE_ALWAYS_ALLOW_MMS);
        }
    }

    /**
     * Set allowing mobile data during voice call.
     *
     * @param allow {@code true} if allowing using data during voice call, {@code false} if
     * disallowed.
     */
    public void setDataAllowedInVoiceCall(boolean allow) {
        if (allow) {
            mRules.add(OVERRIDE_RULE_ALLOW_DATA_DURING_VOICE_CALL);
        } else {
            mRules.remove(OVERRIDE_RULE_ALLOW_DATA_DURING_VOICE_CALL);
        }
    }

    /**
     * Check if data is allowed during voice call.
     *
     * @return {@code true} if data is allowed during voice call.
     */
    public boolean isDataAllowedInVoiceCall() {
        return mRules.contains(OVERRIDE_RULE_ALLOW_DATA_DURING_VOICE_CALL);
    }

    private boolean canSatisfyAnyRule(@ApnType int apnType,
                                      @Condition int providedConditions) {
        for (OverrideRule rule : mRules) {
            if (rule.isSatisfiedByConditions(apnType, providedConditions)) {
                return true;
            }
        }
        return false;
    }

    private @Condition int getCurrentConditions(Phone phone) {
        int conditions = 0;

        if (phone != null) {
            // Check if the device is on voice call
            if (phone.getState() != PhoneConstants.State.IDLE) {
                conditions |= OverrideConditions.CONDITION_IN_VOICE_CALL;
            }

            if (phone.getSubId() != SubscriptionController.getInstance().getDefaultDataSubId()) {
                conditions |= OverrideConditions.CONDITION_NON_DEFAULT;
            }
        }

        return conditions;
    }

    /**
     * Check for given APN type if we should enable data.
     *
     * @param phone Phone object
     * @param apnType APN type
     * @return {@code true} if data should be enabled for the current condition.
     */
    public boolean shouldOverrideDataEnabledSettings(Phone phone, @ApnType int apnType) {
        return canSatisfyAnyRule(apnType, getCurrentConditions(phone));
    }

    /**
     * Get data enabled override rules.
     *
     * @return Get data enabled override rules in string format
     */
    @NonNull
    public String getRules() {
        List<String> ruleStrings = new ArrayList<>();
        for (OverrideRule rule : mRules) {
            ruleStrings.add(rule.toString());
        }
        return TextUtils.join(",", ruleStrings);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        DataEnabledOverride that = (DataEnabledOverride) o;
        return mRules.equals(that.mRules);
    }

    @Override
    public int hashCode() {
        return Objects.hash(mRules);
    }

    @Override
    public String toString() {
        return "DataEnabledOverride: [rules=\"" + getRules() + "\"]";
    }
}
