/*
 * Copyright 2014-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.net.intent;

import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import com.google.common.annotations.Beta;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.FilteredConnectPoint;
import org.onosproject.net.Link;
import org.onosproject.net.NetworkResource;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;

import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableSet;
import org.slf4j.Logger;

import static org.slf4j.LoggerFactory.getLogger;

/**
 * Abstraction of a connectivity intent that is implemented by a set of path
 * segments.
 */
@Beta
public final class LinkCollectionIntent extends ConnectivityIntent {

    private final Set<Link> links;

    private final Set<FilteredConnectPoint> ingressPoints;
    private final Set<FilteredConnectPoint> egressPoints;
    private final boolean egressTreatmentFlag;
    private final double cost;
    private static final int DEFAULT_COST = 1;

    /**
     * Creates a new actionable intent capable of funneling the selected
     * traffic along the specified convergent tree and out the given egress
     * point satisfying the specified constraints.
     *
     * @param appId       application identifier
     * @param key         key to use for the intent
     * @param selector    traffic match
     * @param treatment   action
     * @param links       traversed links
     * @param ingressPoints filtered ingress points
     * @param egressPoints filtered egress points
     * @param constraints optional list of constraints
     * @param priority    priority to use for the flows generated by this intent
     * @param egressTreatment true if treatment should be applied by the egress device
     * @param cost the cost of the links
     * @throws NullPointerException {@code path} is null
     */
    private LinkCollectionIntent(ApplicationId appId,
                                 Key key,
                                 TrafficSelector selector,
                                 TrafficTreatment treatment,
                                 Collection<NetworkResource> resources,
                                 Set<Link> links,
                                 Set<FilteredConnectPoint> ingressPoints,
                                 Set<FilteredConnectPoint> egressPoints,
                                 List<Constraint> constraints,
                                 int priority,
                                 boolean egressTreatment,
                                 double cost) {
        super(appId, key, resources(resources, links), selector, treatment, constraints, priority);
        this.links = links;
        this.ingressPoints = ingressPoints;
        this.egressPoints = egressPoints;
        this.egressTreatmentFlag = egressTreatment;
        this.cost = cost;
    }

    /**
     * Constructor for serializer.
     */
    protected LinkCollectionIntent() {
        this.links = null;
        this.ingressPoints = null;
        this.egressPoints = null;
        this.egressTreatmentFlag = false;
        this.cost = DEFAULT_COST;
    }

    /**
     * Returns a new link collection intent builder. The application id,
     * ingress point and egress points are required fields.  If they are
     * not set by calls to the appropriate methods, an exception will
     * be thrown.
     *
     * @return single point to multi point builder
     */
    public static Builder builder() {
        return new Builder();
    }

    /**
     * Builder of a single point to multi point intent.
     */
    public static final class Builder extends ConnectivityIntent.Builder {
        private final Logger log = getLogger(getClass());
        private Set<Link> links;
        private Set<FilteredConnectPoint> ingressPoints;
        private Set<FilteredConnectPoint> egressPoints;
        private boolean egressTreatmentFlag;
        private double cost;


        private Builder() {
            // Hide constructor
        }

        @Override
        public Builder appId(ApplicationId appId) {
            return (Builder) super.appId(appId);
        }

        @Override
        public Builder key(Key key) {
            return (Builder) super.key(key);
        }

        @Override
        public Builder selector(TrafficSelector selector) {
            return (Builder) super.selector(selector);
        }

        @Override
        public Builder treatment(TrafficTreatment treatment) {
            return (Builder) super.treatment(treatment);
        }

        @Override
        public Builder constraints(List<Constraint> constraints) {
            return (Builder) super.constraints(constraints);
        }

        @Override
        public Builder priority(int priority) {
            return (Builder) super.priority(priority);
        }

        @Override
        public Builder resources(Collection<NetworkResource> resources) {
            return (Builder) super.resources(resources);
        }

        /**
         * Sets the ingress point of the single point to multi point intent
         * that will be built.
         *
         * @param ingressPoints ingress connect points
         * @return this builder
         */
        @Deprecated
        public Builder ingressPoints(Set<ConnectPoint> ingressPoints) {
            if (this.ingressPoints != null) {
                log.warn("Ingress points are already set, " +
                                 "this will override original ingress points.");
            }
            this.ingressPoints = ingressPoints.stream()
                    .map(FilteredConnectPoint::new)
                    .collect(Collectors.toSet());
            return this;
        }

        /**
         * Sets the egress points of the single point to multi point intent
         * that will be built.
         *
         * @param egressPoints egress connect points
         * @return this builder
         */
        @Deprecated
        public Builder egressPoints(Set<ConnectPoint> egressPoints) {
            if (this.egressPoints != null) {
                log.warn("Egress points are already set, " +
                                 "this will override original egress points.");
            }
            this.egressPoints = egressPoints.stream()
                    .map(FilteredConnectPoint::new)
                    .collect(Collectors.toSet());
            return this;
        }

        /**
         * Sets the filtered ingress point of the single point to multi point intent
         * that will be built.
         *
         * @param ingressPoints ingress connect points
         * @return this builder
         */
        public Builder filteredIngressPoints(Set<FilteredConnectPoint> ingressPoints) {
            this.ingressPoints = ImmutableSet.copyOf(ingressPoints);
            return this;
        }

        /**
         * Sets the filtered egress points of the single point to multi point intent
         * that will be built.
         *
         * @param egressPoints egress connect points
         * @return this builder
         */
        public Builder filteredEgressPoints(Set<FilteredConnectPoint> egressPoints) {
            this.egressPoints = ImmutableSet.copyOf(egressPoints);
            return this;
        }

        /**
         * Sets the links of the link collection intent
         * that will be built.
         *
         * @param links links for the intent
         * @return this builder
         */
        public Builder links(Set<Link> links) {
            this.links = ImmutableSet.copyOf(links);
            return this;
        }

        /**
         * Sets the intent to apply treatment at the egress rather than the
         * ingress.
         *
         * @param treatmentOnEgress true applies treatment on egress device
         * @return this builder
         */
        public Builder applyTreatmentOnEgress(boolean treatmentOnEgress) {
            this.egressTreatmentFlag = treatmentOnEgress;
            return this;
        }

        /**
         * Sets the cost for the links of the Intent.
         *
         * @param cost the cost of the links
         * @return this builder
         */
        public Builder cost(double cost) {
            this.cost = cost;
            return this;
        }

        /**
         * Builds a single point to multi point intent from the
         * accumulated parameters.
         *
         * @return point to point intent
         */
        public LinkCollectionIntent build() {

            return new LinkCollectionIntent(
                    appId,
                    key,
                    selector,
                    treatment,
                    resources,
                    links,
                    ingressPoints,
                    egressPoints,
                    constraints,
                    priority,
                    egressTreatmentFlag,
                    cost
            );
        }
    }

    /**
     * Returns the set of links that represent the network connections needed
     * by this intent.
     *
     * @return Set of links for the network hops needed by this intent
     */
    public Set<Link> links() {
        return links;
    }

    /**
     * Returns the ingress points of the intent.
     *
     * @return the ingress points
     */
    public Set<ConnectPoint> ingressPoints() {
        if (this.ingressPoints == null) {
            return null;
        }
        return ingressPoints.stream()
                .map(FilteredConnectPoint::connectPoint)
                .collect(Collectors.toSet());
    }

    /**
     * Returns the egress points of the intent.
     *
     * @return the egress points
     */
    public Set<ConnectPoint> egressPoints() {
        if (this.egressPoints == null) {
            return null;
        }
        return egressPoints.stream()
                .map(FilteredConnectPoint::connectPoint)
                .collect(Collectors.toSet());
    }

    /**
     * Returns the filtered ingress points of the intent.
     *
     * @return the ingress points
     */
    public Set<FilteredConnectPoint> filteredIngressPoints() {
        return ingressPoints;
    }

    /**
     * Returns the egress points of the intent.
     *
     * @return the egress points
     */
    public Set<FilteredConnectPoint> filteredEgressPoints() {
        return egressPoints;
    }

    /**
     * Returns whether treatment should be applied on egress.
     *
     * @return the egress treatment flag
     */
    public boolean applyTreatmentOnEgress() {
        return egressTreatmentFlag;
    }

    /**
     * Returns the cost of the links of this intent.
     *
     * @return the cost of the links
     */
    public double cost() {
        return cost;
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(getClass())
                .add("id", id())
                .add("key", key())
                .add("appId", appId())
                .add("priority", priority())
                .add("resources", resources())
                .add("selector", selector())
                .add("treatment", treatment())
                .add("links", links())
                .add("ingress", ingressPoints())
                .add("egress", egressPoints())
                .add("treatementOnEgress", applyTreatmentOnEgress())
                .add("cost", cost())
                .toString();
    }
}
