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

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
import android.util.SparseArray;

import com.android.internal.util.MessageUtils;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;

/**
 * An event logged when there is a change or event that requires updating the
 * the APF program in place with a new APF program.
 * {@hide}
 */
@TestApi
@SystemApi
public final class ApfProgramEvent implements IpConnectivityLog.Event {

    // Bitflag constants describing what an Apf program filters.
    // Bits are indexeds from LSB to MSB, starting at index 0.
    /** @hide */
    public static final int FLAG_MULTICAST_FILTER_ON = 0;
    /** @hide */
    public static final int FLAG_HAS_IPV4_ADDRESS    = 1;

    /** {@hide} */
    @IntDef(flag = true, value = {FLAG_MULTICAST_FILTER_ON, FLAG_HAS_IPV4_ADDRESS})
    @Retention(RetentionPolicy.SOURCE)
    public @interface Flags {}

    /** @hide */
    @UnsupportedAppUsage
    public final long lifetime;       // Maximum computed lifetime of the program in seconds
    /** @hide */
    @UnsupportedAppUsage
    public final long actualLifetime; // Effective program lifetime in seconds
    /** @hide */
    @UnsupportedAppUsage
    public final int filteredRas;     // Number of RAs filtered by the APF program
    /** @hide */
    @UnsupportedAppUsage
    public final int currentRas;      // Total number of current RAs at generation time
    /** @hide */
    @UnsupportedAppUsage
    public final int programLength;   // Length of the APF program in bytes
    /** @hide */
    @UnsupportedAppUsage
    public final int flags;           // Bitfield compound of FLAG_* constants

    private ApfProgramEvent(long lifetime, long actualLifetime, int filteredRas, int currentRas,
            int programLength, int flags) {
        this.lifetime = lifetime;
        this.actualLifetime = actualLifetime;
        this.filteredRas = filteredRas;
        this.currentRas = currentRas;
        this.programLength = programLength;
        this.flags = flags;
    }

    private ApfProgramEvent(Parcel in) {
        this.lifetime = in.readLong();
        this.actualLifetime = in.readLong();
        this.filteredRas = in.readInt();
        this.currentRas = in.readInt();
        this.programLength = in.readInt();
        this.flags = in.readInt();
    }

    /**
     * Utility to create an instance of {@link ApfProgramEvent}.
     */
    public static final class Builder {
        private long mLifetime;
        private long mActualLifetime;
        private int mFilteredRas;
        private int mCurrentRas;
        private int mProgramLength;
        private int mFlags;

        /**
         * Set the maximum computed lifetime of the program in seconds.
         */
        @NonNull
        public Builder setLifetime(long lifetime) {
            mLifetime = lifetime;
            return this;
        }

        /**
         * Set the effective program lifetime in seconds.
         */
        @NonNull
        public Builder setActualLifetime(long lifetime) {
            mActualLifetime = lifetime;
            return this;
        }

        /**
         * Set the number of RAs filtered by the APF program.
         */
        @NonNull
        public Builder setFilteredRas(int filteredRas) {
            mFilteredRas = filteredRas;
            return this;
        }

        /**
         * Set the total number of current RAs at generation time.
         */
        @NonNull
        public Builder setCurrentRas(int currentRas) {
            mCurrentRas = currentRas;
            return this;
        }

        /**
         * Set the length of the APF program in bytes.
         */
        @NonNull
        public Builder setProgramLength(int programLength) {
            mProgramLength = programLength;
            return this;
        }

        /**
         * Set the flags describing what an Apf program filters.
         */
        @NonNull
        public Builder setFlags(boolean hasIPv4, boolean multicastFilterOn) {
            mFlags = flagsFor(hasIPv4, multicastFilterOn);
            return this;
        }

        /**
         * Build a new {@link ApfProgramEvent}.
         */
        @NonNull
        public ApfProgramEvent build() {
            return new ApfProgramEvent(mLifetime, mActualLifetime, mFilteredRas, mCurrentRas,
                    mProgramLength, mFlags);
        }
    }

    /** @hide */
    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeLong(lifetime);
        out.writeLong(actualLifetime);
        out.writeInt(filteredRas);
        out.writeInt(currentRas);
        out.writeInt(programLength);
        out.writeInt(this.flags);
    }

    /** @hide */
    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public String toString() {
        String lifetimeString = (lifetime < Long.MAX_VALUE) ? lifetime + "s" : "forever";
        return String.format("ApfProgramEvent(%d/%d RAs %dB %ds/%s %s)", filteredRas, currentRas,
                programLength, actualLifetime, lifetimeString, namesOf(flags));
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null || !(obj.getClass().equals(ApfProgramEvent.class))) return false;
        final ApfProgramEvent other = (ApfProgramEvent) obj;
        return lifetime == other.lifetime
                && actualLifetime == other.actualLifetime
                && filteredRas == other.filteredRas
                && currentRas == other.currentRas
                && programLength == other.programLength
                && flags == other.flags;
    }

    /** @hide */
    public static final Parcelable.Creator<ApfProgramEvent> CREATOR
            = new Parcelable.Creator<ApfProgramEvent>() {
        public ApfProgramEvent createFromParcel(Parcel in) {
            return new ApfProgramEvent(in);
        }

        public ApfProgramEvent[] newArray(int size) {
            return new ApfProgramEvent[size];
        }
    };

    /** @hide */
    @UnsupportedAppUsage
    public static @Flags int flagsFor(boolean hasIPv4, boolean multicastFilterOn) {
        int bitfield = 0;
        if (hasIPv4) {
            bitfield |= (1 << FLAG_HAS_IPV4_ADDRESS);
        }
        if (multicastFilterOn) {
            bitfield |= (1 << FLAG_MULTICAST_FILTER_ON);
        }
        return bitfield;
    }

    private static String namesOf(@Flags int bitfield) {
        List<String> names = new ArrayList<>(Integer.bitCount(bitfield));
        BitSet set = BitSet.valueOf(new long[]{bitfield & Integer.MAX_VALUE});
        // Only iterate over flag bits which are set.
        for (int bit = set.nextSetBit(0); bit >= 0; bit = set.nextSetBit(bit+1)) {
            names.add(Decoder.constants.get(bit));
        }
        return TextUtils.join("|", names);
    }

    final static class Decoder {
        static final SparseArray<String> constants =
                MessageUtils.findMessageNames(
                       new Class[]{ApfProgramEvent.class}, new String[]{"FLAG_"});
    }
}
