/*
 * Copyright (C) 2011 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.settingslib;

import static android.net.NetworkPolicy.CYCLE_NONE;
import static android.net.NetworkPolicy.LIMIT_DISABLED;
import static android.net.NetworkPolicy.SNOOZE_NEVER;
import static android.net.NetworkPolicy.WARNING_DISABLED;
import static android.net.NetworkTemplate.MATCH_WIFI;

import static com.android.internal.util.Preconditions.checkNotNull;

import android.net.NetworkPolicy;
import android.net.NetworkPolicyManager;
import android.net.NetworkTemplate;
import android.net.wifi.WifiInfo;
import android.os.AsyncTask;
import android.text.TextUtils;
import android.util.RecurrenceRule;

import com.google.android.collect.Lists;

import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.ArrayList;

/**
 * Utility class to modify list of {@link NetworkPolicy}. Specifically knows
 * about which policies can coexist. This editor offers thread safety when
 * talking with {@link NetworkPolicyManager}.
 *
 * @hide
 */
public class NetworkPolicyEditor {
    // TODO: be more robust when missing policies from service

    public static final boolean ENABLE_SPLIT_POLICIES = false;

    private NetworkPolicyManager mPolicyManager;
    private ArrayList<NetworkPolicy> mPolicies = Lists.newArrayList();

    public NetworkPolicyEditor(NetworkPolicyManager policyManager) {
        mPolicyManager = checkNotNull(policyManager);
    }

    public void read() {
        final NetworkPolicy[] policies = mPolicyManager.getNetworkPolicies();

        boolean modified = false;
        mPolicies.clear();
        for (NetworkPolicy policy : policies) {
            // TODO: find better place to clamp these
            if (policy.limitBytes < -1) {
                policy.limitBytes = LIMIT_DISABLED;
                modified = true;
            }
            if (policy.warningBytes < -1) {
                policy.warningBytes = WARNING_DISABLED;
                modified = true;
            }

            mPolicies.add(policy);
        }

        // when we cleaned policies above, write back changes
        if (modified) writeAsync();
    }

    public void writeAsync() {
        // TODO: consider making more robust by passing through service
        final NetworkPolicy[] policies = mPolicies.toArray(new NetworkPolicy[mPolicies.size()]);
        new AsyncTask<Void, Void, Void>() {
            @Override
            protected Void doInBackground(Void... params) {
                write(policies);
                return null;
            }
        }.execute();
    }

    public void write(NetworkPolicy[] policies) {
        mPolicyManager.setNetworkPolicies(policies);
    }

    public boolean hasLimitedPolicy(NetworkTemplate template) {
        final NetworkPolicy policy = getPolicy(template);
        return policy != null && policy.limitBytes != LIMIT_DISABLED;
    }

    public NetworkPolicy getOrCreatePolicy(NetworkTemplate template) {
        NetworkPolicy policy = getPolicy(template);
        if (policy == null) {
            policy = buildDefaultPolicy(template);
            mPolicies.add(policy);
        }
        return policy;
    }

    public NetworkPolicy getPolicy(NetworkTemplate template) {
        for (NetworkPolicy policy : mPolicies) {
            if (policy.template.equals(template)) {
                return policy;
            }
        }
        return null;
    }

    public NetworkPolicy getPolicyMaybeUnquoted(NetworkTemplate template) {
        NetworkPolicy policy = getPolicy(template);
        if (policy != null) {
            return policy;
        } else {
            return getPolicy(buildUnquotedNetworkTemplate(template));
        }
    }

    @Deprecated
    private static NetworkPolicy buildDefaultPolicy(NetworkTemplate template) {
        // TODO: move this into framework to share with NetworkPolicyManagerService
        final RecurrenceRule cycleRule;
        final boolean metered;

        if (template.getMatchRule() == MATCH_WIFI) {
            cycleRule = RecurrenceRule.buildNever();
            metered = false;
        } else {
            cycleRule = RecurrenceRule.buildRecurringMonthly(ZonedDateTime.now().getDayOfMonth(),
                    ZoneId.systemDefault());
            metered = true;
        }

        return new NetworkPolicy(template, cycleRule, WARNING_DISABLED,
                LIMIT_DISABLED, SNOOZE_NEVER, SNOOZE_NEVER, metered, true);
    }

    @Deprecated
    public int getPolicyCycleDay(NetworkTemplate template) {
        final NetworkPolicy policy = getPolicy(template);
        if (policy != null && policy.cycleRule.isMonthly()) {
            return policy.cycleRule.start.getDayOfMonth();
        } else {
            return CYCLE_NONE;
        }
    }

    @Deprecated
    public void setPolicyCycleDay(NetworkTemplate template, int cycleDay, String cycleTimezone) {
        final NetworkPolicy policy = getOrCreatePolicy(template);
        policy.cycleRule = NetworkPolicy.buildRule(cycleDay, ZoneId.of(cycleTimezone));
        policy.inferred = false;
        policy.clearSnooze();
        writeAsync();
    }

    public long getPolicyWarningBytes(NetworkTemplate template) {
        final NetworkPolicy policy = getPolicy(template);
        return (policy != null) ? policy.warningBytes : WARNING_DISABLED;
    }

    private void setPolicyWarningBytesInner(NetworkTemplate template, long warningBytes) {
        final NetworkPolicy policy = getOrCreatePolicy(template);
        policy.warningBytes = warningBytes;
        policy.inferred = false;
        policy.clearSnooze();
        writeAsync();
    }

    public void setPolicyWarningBytes(NetworkTemplate template, long warningBytes) {
        long limitBytes = getPolicyLimitBytes(template);

        warningBytes =
            (limitBytes == LIMIT_DISABLED) ? warningBytes : Math.min(warningBytes, limitBytes);

        setPolicyWarningBytesInner(template, warningBytes);
    }

    public long getPolicyLimitBytes(NetworkTemplate template) {
        final NetworkPolicy policy = getPolicy(template);
        return (policy != null) ? policy.limitBytes : LIMIT_DISABLED;
    }


    public void setPolicyLimitBytes(NetworkTemplate template, long limitBytes) {
        long warningBytes = getPolicyWarningBytes(template);

        if (warningBytes > limitBytes && limitBytes != LIMIT_DISABLED) {
            setPolicyWarningBytesInner(template, limitBytes);
        }

        final NetworkPolicy policy = getOrCreatePolicy(template);
        policy.limitBytes = limitBytes;
        policy.inferred = false;
        policy.clearSnooze();
        writeAsync();
    }

    /**
     * Build a revised {@link NetworkTemplate} that matches the same rule, but
     * with an unquoted {@link NetworkTemplate#getNetworkId()}. Used to work
     * around legacy bugs.
     */
    private static NetworkTemplate buildUnquotedNetworkTemplate(NetworkTemplate template) {
        if (template == null) return null;
        final String networkId = template.getNetworkId();
        final String strippedNetworkId = WifiInfo.removeDoubleQuotes(networkId);
        if (!TextUtils.equals(strippedNetworkId, networkId)) {
            return new NetworkTemplate(
                    template.getMatchRule(), template.getSubscriberId(), strippedNetworkId);
        } else {
            return null;
        }
    }
}
