/*
 * Copyright 2015-present Open Networking Laboratory
 *
 * 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 org.onosproject.routing.bgp;

import com.google.common.base.MoreObjects;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;

import java.util.ArrayList;
import java.util.Objects;

import static com.google.common.base.Preconditions.checkNotNull;

/**
 * Represents a route in BGP.
 */
public class BgpRouteEntry extends RouteEntry {
    private final BgpSession bgpSession; // The BGP Session the route was
                                         // received on
    private final byte origin;          // Route ORIGIN: IGP, EGP, INCOMPLETE
    private final AsPath asPath;        // The AS Path
    private final long localPref;       // The local preference for the route
    private long multiExitDisc = BgpConstants.Update.MultiExitDisc.LOWEST_MULTI_EXIT_DISC;

    /**
     * Class constructor.
     *
     * @param bgpSession the BGP Session the route was received on
     * @param prefix the prefix of the route
     * @param nextHop the next hop of the route
     * @param origin the route origin: 0=IGP, 1=EGP, 2=INCOMPLETE
     * @param asPath the AS path
     * @param localPref the route local preference
     */
    public BgpRouteEntry(BgpSession bgpSession, IpPrefix prefix,
                         IpAddress nextHop, byte origin,
                         BgpRouteEntry.AsPath asPath, long localPref) {
        super(prefix, nextHop);
        this.bgpSession = checkNotNull(bgpSession);
        this.origin = origin;
        this.asPath = checkNotNull(asPath);
        this.localPref = localPref;
    }

    /**
     * Gets the BGP Session the route was received on.
     *
     * @return the BGP Session the route was received on
     */
    public BgpSession getBgpSession() {
        return bgpSession;
    }

    /**
     * Gets the route origin: 0=IGP, 1=EGP, 2=INCOMPLETE.
     *
     * @return the route origin: 0=IGP, 1=EGP, 2=INCOMPLETE
     */
    public byte getOrigin() {
        return origin;
    }

    /**
     * Gets the route AS path.
     *
     * @return the route AS path
     */
    public BgpRouteEntry.AsPath getAsPath() {
        return asPath;
    }

    /**
     * Gets the route local preference.
     *
     * @return the route local preference
     */
    public long getLocalPref() {
        return localPref;
    }

    /**
     * Gets the route MED (Multi-Exit Discriminator).
     *
     * @return the route MED (Multi-Exit Discriminator)
     */
    public long getMultiExitDisc() {
        return multiExitDisc;
    }

    /**
     * Sets the route MED (Multi-Exit Discriminator).
     *
     * @param multiExitDisc the route MED (Multi-Exit Discriminator) to set
     */
    void setMultiExitDisc(long multiExitDisc) {
        this.multiExitDisc = multiExitDisc;
    }

    /**
     * Tests whether the route is originated from the local AS.
     * <p>
     * The route is considered originated from the local AS if the AS Path
     * is empty or if it begins with an AS_SET (after skipping
     * AS_CONFED_SEQUENCE and AS_CONFED_SET).
     * </p>
     *
     * @return true if the route is originated from the local AS, otherwise
     * false
     */
    boolean isLocalRoute() {
        PathSegment firstPathSegment = null;

        // Find the first Path Segment by ignoring the AS_CONFED_* segments
        for (PathSegment pathSegment : asPath.getPathSegments()) {
            if ((pathSegment.getType() == BgpConstants.Update.AsPath.AS_SET) ||
                (pathSegment.getType() == BgpConstants.Update.AsPath.AS_SEQUENCE)) {
                firstPathSegment = pathSegment;
                break;
            }
        }
        if (firstPathSegment == null) {
            return true;                // Local route: no path segments
        }
        // If the first path segment is AS_SET, the route is considered local
        if (firstPathSegment.getType() == BgpConstants.Update.AsPath.AS_SET) {
            return true;
        }

        return false;                   // The route is not local
    }

    /**
     * Gets the BGP Neighbor AS number the route was received from.
     * <p>
     * If the router is originated from the local AS, the return value is
     * zero (BGP_AS_0).
     * </p>
     *
     * @return the BGP Neighbor AS number the route was received from.
     */
    long getNeighborAs() {
        PathSegment firstPathSegment = null;

        if (isLocalRoute()) {
            return BgpConstants.BGP_AS_0;
        }

        // Find the first Path Segment by ignoring the AS_CONFED_* segments
        for (PathSegment pathSegment : asPath.getPathSegments()) {
            if ((pathSegment.getType() == BgpConstants.Update.AsPath.AS_SET) ||
                (pathSegment.getType() == BgpConstants.Update.AsPath.AS_SEQUENCE)) {
                firstPathSegment = pathSegment;
                break;
            }
        }
        if (firstPathSegment == null) {
            // NOTE: Shouldn't happen - should be captured by isLocalRoute()
            return BgpConstants.BGP_AS_0;
        }

        if (firstPathSegment.getSegmentAsNumbers().isEmpty()) {
            // NOTE: Shouldn't happen. Should check during the parsing.
            return BgpConstants.BGP_AS_0;
        }
        return firstPathSegment.getSegmentAsNumbers().get(0);
    }

    /**
     * Tests whether the AS Path contains a loop.
     * <p>
     * The test is done by comparing whether the AS Path contains the
     * local AS number.
     * </p>
     *
     * @param localAsNumber the local AS number to compare against
     * @return true if the AS Path contains a loop, otherwise false
     */
    boolean hasAsPathLoop(long localAsNumber) {
        for (PathSegment pathSegment : asPath.getPathSegments()) {
            for (Long asNumber : pathSegment.getSegmentAsNumbers()) {
                if (asNumber.equals(localAsNumber)) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Compares this BGP route against another BGP route by using the
     * BGP Decision Process.
     * <p>
     * NOTE: The comparison needs to be performed only on routes that have
     * same IP Prefix.
     * </p>
     *
     * @param other the BGP route to compare against
     * @return true if this BGP route is better than the other BGP route
     * or same, otherwise false
     */
    boolean isBetterThan(BgpRouteEntry other) {
        if (this == other) {
            return true;        // Return true if same route
        }

        // Compare the LOCAL_PREF values: larger is better
        if (getLocalPref() != other.getLocalPref()) {
            return (getLocalPref() > other.getLocalPref());
        }

        // Compare the AS number in the path: smaller is better
        if (getAsPath().getAsPathLength() !=
            other.getAsPath().getAsPathLength()) {
            return getAsPath().getAsPathLength() <
                other.getAsPath().getAsPathLength();
        }

        // Compare the Origin number: lower is better
        if (getOrigin() != other.getOrigin()) {
            return (getOrigin() < other.getOrigin());
        }

        // Compare the MED if the neighbor AS is same: larger is better
        medLabel: {
            if (isLocalRoute() || other.isLocalRoute()) {
                // Compare MEDs for non-local routes only
                break medLabel;
            }
            long thisNeighborAs = getNeighborAs();
            if (thisNeighborAs != other.getNeighborAs()) {
                break medLabel;             // AS number is different
            }
            if (thisNeighborAs == BgpConstants.BGP_AS_0) {
                break medLabel;             // Invalid AS number
            }

            // Compare the MED
            if (getMultiExitDisc() != other.getMultiExitDisc()) {
                return (getMultiExitDisc() > other.getMultiExitDisc());
            }
        }

        // Compare the peer BGP ID: lower is better
        Ip4Address peerBgpId = getBgpSession().remoteInfo().bgpId();
        Ip4Address otherPeerBgpId = other.getBgpSession().remoteInfo().bgpId();
        if (!peerBgpId.equals(otherPeerBgpId)) {
            return (peerBgpId.compareTo(otherPeerBgpId) < 0);
        }

        // Compare the peer BGP address: lower is better
        Ip4Address peerAddress = getBgpSession().remoteInfo().ip4Address();
        Ip4Address otherPeerAddress =
            other.getBgpSession().remoteInfo().ip4Address();
        if (!peerAddress.equals(otherPeerAddress)) {
            return (peerAddress.compareTo(otherPeerAddress) < 0);
        }

        return true;            // Routes are same. Shouldn't happen?
    }

    /**
     * A class to represent AS Path Segment.
     */
    public static class PathSegment {
        // Segment type: AS_SET(1), AS_SEQUENCE(2), AS_CONFED_SEQUENCE(3),
        // AS_CONFED_SET(4)
        private final byte type;
        private final ArrayList<Long> segmentAsNumbers;   // Segment AS numbers

        /**
         * Constructor.
         *
         * @param type the Path Segment Type: AS_SET(1), AS_SEQUENCE(2),
         * AS_CONFED_SEQUENCE(3), AS_CONFED_SET(4)
         * @param segmentAsNumbers the Segment AS numbers
         */
        PathSegment(byte type, ArrayList<Long> segmentAsNumbers) {
            this.type = type;
            this.segmentAsNumbers = checkNotNull(segmentAsNumbers);
        }

        /**
         * Gets the Path Segment Type: AS_SET(1), AS_SEQUENCE(2),
         * AS_CONFED_SEQUENCE(3), AS_CONFED_SET(4).
         *
         * @return the Path Segment Type: AS_SET(1), AS_SEQUENCE(2),
         * AS_CONFED_SEQUENCE(3), AS_CONFED_SET(4)
         */
        public byte getType() {
            return type;
        }

        /**
         * Gets the Path Segment AS Numbers.
         *
         * @return the Path Segment AS Numbers
         */
        public ArrayList<Long> getSegmentAsNumbers() {
            return segmentAsNumbers;
        }

        @Override
        public boolean equals(Object other) {
            if (this == other) {
                return true;
            }

            if (!(other instanceof PathSegment)) {
                return false;
            }

            PathSegment otherPathSegment = (PathSegment) other;
            return Objects.equals(this.type, otherPathSegment.type) &&
                Objects.equals(this.segmentAsNumbers,
                               otherPathSegment.segmentAsNumbers);
        }

        @Override
        public int hashCode() {
            return Objects.hash(type, segmentAsNumbers);
        }

        @Override
        public String toString() {
            return MoreObjects.toStringHelper(getClass())
                .add("type", BgpConstants.Update.AsPath.typeToString(type))
                .add("segmentAsNumbers", this.segmentAsNumbers)
                .toString();
        }
    }

    /**
     * A class to represent AS Path.
     */
    public static class AsPath {
        private final ArrayList<PathSegment> pathSegments;
        private final int asPathLength;         // Precomputed AS Path Length

        /**
         * Constructor.
         *
         * @param pathSegments the Path Segments of the Path
         */
         AsPath(ArrayList<PathSegment> pathSegments) {
             this.pathSegments = checkNotNull(pathSegments);

             //
             // Precompute the AS Path Length:
             // - AS_SET counts as 1
             // - AS_SEQUENCE counts how many AS numbers are included
             // - AS_CONFED_SEQUENCE and AS_CONFED_SET are ignored
             //
             int pl = 0;
             for (PathSegment pathSegment : pathSegments) {
                 switch (pathSegment.getType()) {
                 case BgpConstants.Update.AsPath.AS_SET:
                     pl++;              // AS_SET counts as 1
                     break;
                 case BgpConstants.Update.AsPath.AS_SEQUENCE:
                     // Count each AS number
                     pl += pathSegment.getSegmentAsNumbers().size();
                     break;
                 case BgpConstants.Update.AsPath.AS_CONFED_SEQUENCE:
                     break;             // Ignore
                 case BgpConstants.Update.AsPath.AS_CONFED_SET:
                     break;             // Ignore
                 default:
                     // NOTE: What to do if the Path Segment type is unknown?
                     break;
                 }
             }
             asPathLength = pl;
         }

        /**
         * Gets the AS Path Segments.
         *
         * @return the AS Path Segments
         */
        public ArrayList<PathSegment> getPathSegments() {
            return pathSegments;
        }

        /**
         * Gets the AS Path Length as considered by the BGP Decision Process.
         *
         * @return the AS Path Length as considered by the BGP Decision Process
         */
        int getAsPathLength() {
            return asPathLength;
        }

        @Override
        public boolean equals(Object other) {
            if (this == other) {
                return true;
            }

            if (!(other instanceof AsPath)) {
                return false;
            }

            AsPath otherAsPath = (AsPath) other;
            return Objects.equals(this.pathSegments, otherAsPath.pathSegments);
        }

        @Override
        public int hashCode() {
            return pathSegments.hashCode();
        }

        @Override
        public String toString() {
            return MoreObjects.toStringHelper(getClass())
                .add("pathSegments", this.pathSegments)
                .toString();
        }
    }

    /**
     * Compares whether two objects are equal.
     * <p>
     * NOTE: The bgpSession field is excluded from the comparison.
     * </p>
     *
     * @return true if the two objects are equal, otherwise false.
     */
    @Override
    public boolean equals(Object other) {
        if (this == other) {
            return true;
        }

        //
        // NOTE: Subclasses are considered as change of identity, hence
        // equals() will return false if the class type doesn't match.
        //
        if (other == null || getClass() != other.getClass()) {
            return false;
        }

        if (!super.equals(other)) {
            return false;
        }

        // NOTE: The bgpSession field is excluded from the comparison
        BgpRouteEntry otherRoute = (BgpRouteEntry) other;
        return (this.origin == otherRoute.origin) &&
            Objects.equals(this.asPath, otherRoute.asPath) &&
            (this.localPref == otherRoute.localPref) &&
            (this.multiExitDisc == otherRoute.multiExitDisc);
    }

    /**
     * Computes the hash code.
     * <p>
     * NOTE: We return the base class hash code to avoid expensive computation
     * </p>
     *
     * @return the object hash code
     */
    @Override
    public int hashCode() {
        return super.hashCode();
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(getClass())
            .add("prefix", prefix())
            .add("nextHop", nextHop())
            .add("bgpId", bgpSession.remoteInfo().bgpId())
            .add("origin", BgpConstants.Update.Origin.typeToString(origin))
            .add("asPath", asPath)
            .add("localPref", localPref)
            .add("multiExitDisc", multiExitDisc)
            .toString();
    }
}
