/*
 * 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 android.net.ipmemorystore;

import android.annotation.NonNull;
import android.annotation.Nullable;

import com.android.internal.annotations.VisibleForTesting;

import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.StringJoiner;

/**
 * A POD object to represent attributes of a single L2 network entry.
 * @hide
 */
public class NetworkAttributes {
    private static final boolean DBG = true;

    // Weight cutoff for grouping. To group, a similarity score is computed with the following
    // algorithm : if both fields are non-null and equals() then add their assigned weight, else if
    // both are null then add a portion of their assigned weight (see NULL_MATCH_WEIGHT),
    // otherwise add nothing.
    // As a guideline, this should be something like 60~75% of the total weights in this class. The
    // design states "in essence a reader should imagine that if two important columns don't match,
    // or one important and several unimportant columns don't match then the two records are
    // considered a different group".
    private static final float TOTAL_WEIGHT_CUTOFF = 520.0f;
    // The portion of the weight that is earned when scoring group-sameness by having both columns
    // being null. This is because some networks rightfully don't have some attributes (e.g. a
    // V6-only network won't have an assigned V4 address) and both being null should count for
    // something, but attributes may also be null just because data is unavailable.
    private static final float NULL_MATCH_WEIGHT = 0.25f;

    // The v4 address that was assigned to this device the last time it joined this network.
    // This typically comes from DHCP but could be something else like static configuration.
    // This does not apply to IPv6.
    // TODO : add a list of v6 prefixes for the v6 case.
    @Nullable
    public final Inet4Address assignedV4Address;
    private static final float WEIGHT_ASSIGNEDV4ADDR = 300.0f;

    // Optionally supplied by the client if it has an opinion on L3 network. For example, this
    // could be a hash of the SSID + security type on WiFi.
    @Nullable
    public final String groupHint;
    private static final float WEIGHT_GROUPHINT = 300.0f;

    // The list of DNS server addresses.
    @Nullable
    public final List<InetAddress> dnsAddresses;
    private static final float WEIGHT_DNSADDRESSES = 200.0f;

    // The mtu on this network.
    @Nullable
    public final Integer mtu;
    private static final float WEIGHT_MTU = 50.0f;

    // The sum of all weights in this class. Tests ensure that this stays equal to the total of
    // all weights.
    /** @hide */
    @VisibleForTesting
    public static final float TOTAL_WEIGHT = WEIGHT_ASSIGNEDV4ADDR
            + WEIGHT_GROUPHINT
            + WEIGHT_DNSADDRESSES
            + WEIGHT_MTU;

    /** @hide */
    @VisibleForTesting
    public NetworkAttributes(
            @Nullable final Inet4Address assignedV4Address,
            @Nullable final String groupHint,
            @Nullable final List<InetAddress> dnsAddresses,
            @Nullable final Integer mtu) {
        if (mtu != null && mtu < 0) throw new IllegalArgumentException("MTU can't be negative");
        this.assignedV4Address = assignedV4Address;
        this.groupHint = groupHint;
        this.dnsAddresses = null == dnsAddresses ? null :
                Collections.unmodifiableList(new ArrayList<>(dnsAddresses));
        this.mtu = mtu;
    }

    @VisibleForTesting
    public NetworkAttributes(@NonNull final NetworkAttributesParcelable parcelable) {
        // The call to the other constructor must be the first statement of this constructor,
        // so everything has to be inline
        this((Inet4Address) getByAddressOrNull(parcelable.assignedV4Address),
                parcelable.groupHint,
                blobArrayToInetAddressList(parcelable.dnsAddresses),
                parcelable.mtu >= 0 ? parcelable.mtu : null);
    }

    @Nullable
    private static InetAddress getByAddressOrNull(@Nullable final byte[] address) {
        try {
            return InetAddress.getByAddress(address);
        } catch (UnknownHostException e) {
            return null;
        }
    }

    @Nullable
    private static List<InetAddress> blobArrayToInetAddressList(@Nullable final Blob[] blobs) {
        if (null == blobs) return null;
        final ArrayList<InetAddress> list = new ArrayList<>(blobs.length);
        for (final Blob b : blobs) {
            final InetAddress addr = getByAddressOrNull(b.data);
            if (null != addr) list.add(addr);
        }
        return list;
    }

    @Nullable
    private static Blob[] inetAddressListToBlobArray(@Nullable final List<InetAddress> addresses) {
        if (null == addresses) return null;
        final ArrayList<Blob> blobs = new ArrayList<>();
        for (int i = 0; i < addresses.size(); ++i) {
            final InetAddress addr = addresses.get(i);
            if (null == addr) continue;
            final Blob b = new Blob();
            b.data = addr.getAddress();
            blobs.add(b);
        }
        return blobs.toArray(new Blob[0]);
    }

    /** Converts this NetworkAttributes to a parcelable object */
    @NonNull
    public NetworkAttributesParcelable toParcelable() {
        final NetworkAttributesParcelable parcelable = new NetworkAttributesParcelable();
        parcelable.assignedV4Address =
                (null == assignedV4Address) ? null : assignedV4Address.getAddress();
        parcelable.groupHint = groupHint;
        parcelable.dnsAddresses = inetAddressListToBlobArray(dnsAddresses);
        parcelable.mtu = (null == mtu) ? -1 : mtu;
        return parcelable;
    }

    private float samenessContribution(final float weight,
            @Nullable final Object o1, @Nullable final Object o2) {
        if (null == o1) {
            return (null == o2) ? weight * NULL_MATCH_WEIGHT : 0f;
        }
        return Objects.equals(o1, o2) ? weight : 0f;
    }

    /** @hide */
    public float getNetworkGroupSamenessConfidence(@NonNull final NetworkAttributes o) {
        final float samenessScore =
                samenessContribution(WEIGHT_ASSIGNEDV4ADDR, assignedV4Address, o.assignedV4Address)
                + samenessContribution(WEIGHT_GROUPHINT, groupHint, o.groupHint)
                + samenessContribution(WEIGHT_DNSADDRESSES, dnsAddresses, o.dnsAddresses)
                + samenessContribution(WEIGHT_MTU, mtu, o.mtu);
        // The minimum is 0, the max is TOTAL_WEIGHT and should be represented by 1.0, and
        // TOTAL_WEIGHT_CUTOFF should represent 0.5, but there is no requirement that
        // TOTAL_WEIGHT_CUTOFF would be half of TOTAL_WEIGHT (indeed, it should not be).
        // So scale scores under the cutoff between 0 and 0.5, and the scores over the cutoff
        // between 0.5 and 1.0.
        if (samenessScore < TOTAL_WEIGHT_CUTOFF) {
            return samenessScore / (TOTAL_WEIGHT_CUTOFF * 2);
        } else {
            return (samenessScore - TOTAL_WEIGHT_CUTOFF) / (TOTAL_WEIGHT - TOTAL_WEIGHT_CUTOFF) / 2
                    + 0.5f;
        }
    }

    /** @hide */
    public static class Builder {
        @Nullable
        private Inet4Address mAssignedAddress;
        @Nullable
        private String mGroupHint;
        @Nullable
        private List<InetAddress> mDnsAddresses;
        @Nullable
        private Integer mMtu;

        /**
         * Set the assigned address.
         * @param assignedV4Address The assigned address.
         * @return This builder.
         */
        public Builder setAssignedV4Address(@Nullable final Inet4Address assignedV4Address) {
            mAssignedAddress = assignedV4Address;
            return this;
        }

        /**
         * Set the group hint.
         * @param groupHint The group hint.
         * @return This builder.
         */
        public Builder setGroupHint(@Nullable final String groupHint) {
            mGroupHint = groupHint;
            return this;
        }

        /**
         * Set the DNS addresses.
         * @param dnsAddresses The DNS addresses.
         * @return This builder.
         */
        public Builder setDnsAddresses(@Nullable final List<InetAddress> dnsAddresses) {
            if (DBG && null != dnsAddresses) {
                // Parceling code crashes if one of the addresses is null, therefore validate
                // them when running in debug.
                for (final InetAddress address : dnsAddresses) {
                    if (null == address) throw new IllegalArgumentException("Null DNS address");
                }
            }
            this.mDnsAddresses = dnsAddresses;
            return this;
        }

        /**
         * Set the MTU.
         * @param mtu The MTU.
         * @return This builder.
         */
        public Builder setMtu(@Nullable final Integer mtu) {
            if (null != mtu && mtu < 0) throw new IllegalArgumentException("MTU can't be negative");
            mMtu = mtu;
            return this;
        }

        /**
         * Return the built NetworkAttributes object.
         * @return The built NetworkAttributes object.
         */
        public NetworkAttributes build() {
            return new NetworkAttributes(mAssignedAddress, mGroupHint, mDnsAddresses, mMtu);
        }
    }

    @Override
    public boolean equals(@Nullable final Object o) {
        if (!(o instanceof NetworkAttributes)) return false;
        final NetworkAttributes other = (NetworkAttributes) o;
        return Objects.equals(assignedV4Address, other.assignedV4Address)
                && Objects.equals(groupHint, other.groupHint)
                && Objects.equals(dnsAddresses, other.dnsAddresses)
                && Objects.equals(mtu, other.mtu);
    }

    @Override
    public int hashCode() {
        return Objects.hash(assignedV4Address, groupHint, dnsAddresses, mtu);
    }

    /** Pretty print */
    @Override
    public String toString() {
        final StringJoiner resultJoiner = new StringJoiner(" ", "{", "}");
        final ArrayList<String> nullFields = new ArrayList<>();

        if (null != assignedV4Address) {
            resultJoiner.add("assignedV4Addr :");
            resultJoiner.add(assignedV4Address.toString());
        } else {
            nullFields.add("assignedV4Addr");
        }

        if (null != groupHint) {
            resultJoiner.add("groupHint :");
            resultJoiner.add(groupHint);
        } else {
            nullFields.add("groupHint");
        }

        if (null != dnsAddresses) {
            resultJoiner.add("dnsAddr : [");
            for (final InetAddress addr : dnsAddresses) {
                resultJoiner.add(addr.getHostAddress());
            }
            resultJoiner.add("]");
        } else {
            nullFields.add("dnsAddr");
        }

        if (null != mtu) {
            resultJoiner.add("mtu :");
            resultJoiner.add(mtu.toString());
        } else {
            nullFields.add("mtu");
        }

        if (!nullFields.isEmpty()) {
            resultJoiner.add("; Null fields : [");
            for (final String field : nullFields) {
                resultJoiner.add(field);
            }
            resultJoiner.add("]");
        }

        return resultJoiner.toString();
    }
}
