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

import org.onosproject.core.ApplicationId;
import org.onosproject.net.Link;
import org.onosproject.net.Path;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;

import com.google.common.base.MoreObjects;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;

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

/**
 * Abstraction of explicitly path specified connectivity intent.
 */
public class PathIntent extends ConnectivityIntent {

    private final Path path;

    /**
     * Creates a new point-to-point intent with the supplied ingress/egress
     * ports and using the specified explicit path.
     *
     * @param appId     application identifier
     * @param selector  traffic selector
     * @param treatment treatment
     * @param path      traversed links
     * @param constraints  optional list of constraints
     * @param priority  priority to use for the generated flows
     * @throws NullPointerException {@code path} is null
     */
    protected PathIntent(ApplicationId appId,
                         TrafficSelector selector,
                         TrafficTreatment treatment,
                         Path path,
                         List<Constraint> constraints,
                         int priority) {
        super(appId, null, resources(path.links()), selector, treatment, constraints,
                priority);
        PathIntent.validate(path.links());
        this.path = path;
    }

    /**
     * Constructor for serializer.
     */
    protected PathIntent() {
        super();
        this.path = null;
    }

    /**
     * Returns a new host to host intent builder.
     *
     * @return host to host intent builder
     */
    public static Builder builder() {
        return new Builder();
    }

    /**
     * Builder of a host to host intent.
     */
    public static class Builder extends ConnectivityIntent.Builder {
        Path path;

        protected Builder() {
            // Hide default 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);
        }

        /**
         * Sets the path of the intent that will be built.
         *
         * @param path path for the intent
         * @return this builder
         */
        public Builder path(Path path) {
            this.path = path;
            return this;
        }

        /**
         * Builds a path intent from the accumulated parameters.
         *
         * @return point to point intent
         */
        public PathIntent build() {

            return new PathIntent(
                    appId,
                    selector,
                    treatment,
                    path,
                    constraints,
                    priority
            );
        }
    }



    // NOTE: This methods takes linear time with the number of links.
    /**
     * Validates that source element ID and destination element ID of a link are
     * different for the specified all links and that destination element ID of a link and source
     * element ID of the next adjacent source element ID are same for the specified all links.
     *
     * @param links links to be validated
     */
    public static void validate(List<Link> links) {
        checkArgument(Iterables.all(links, new Predicate<Link>() {
            @Override
            public boolean apply(Link link) {
                return !link.src().elementId().equals(link.dst().elementId());
            }
        }), "element of src and dst in a link must be different: {}", links);

        boolean adjacentSame = true;
        for (int i = 0; i < links.size() - 1; i++) {
            if (!links.get(i).dst().elementId().equals(links.get(i + 1).src().elementId())) {
                adjacentSame = false;
                break;
            }
        }
        checkArgument(adjacentSame, "adjacent links must share the same element: {}", links);
    }

    /**
     * Returns the links which the traffic goes along.
     *
     * @return traversed links
     */
    public Path path() {
        return path;
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(getClass())
                .add("id", id())
                .add("appId", appId())
                .add("priority", priority())
                .add("resources", resources())
                .add("selector", selector())
                .add("treatment", treatment())
                .add("constraints", constraints())
                .add("path", path)
                .toString();
    }

}
