/*
 * Copyright 2015 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.flowobjective;

import com.google.common.annotations.Beta;
import com.google.common.collect.ImmutableList;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;

import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

import static com.google.common.base.MoreObjects.toStringHelper;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

/**
 * Default implementation of a next objective.
 */
@Beta
public final class DefaultNextObjective implements NextObjective {

    private final List<TrafficTreatment> treatments;
    private final ApplicationId appId;
    private final Type type;
    private final Integer id;
    private final Operation op;
    private final Optional<ObjectiveContext> context;
    private final TrafficSelector meta;

    private DefaultNextObjective(Builder builder) {
        this.treatments = builder.treatments;
        this.appId = builder.appId;
        this.type = builder.type;
        this.id = builder.id;
        this.op = builder.op;
        this.context = Optional.ofNullable(builder.context);
        this.meta = builder.meta;
    }

    @Override
    public Collection<TrafficTreatment> next() {
        return treatments;
    }

    @Override
    public Type type() {
        return type;
    }

    @Override
    public int id() {
        return id;
    }

    @Override
    public int priority() {
        return 0;
    }

    @Override
    public ApplicationId appId() {
        return appId;
    }

    @Override
    public int timeout() {
        return 0;
    }

    @Override
    public boolean permanent() {
        return false;
    }

    @Override
    public Operation op() {
        return op;
    }

    @Override
    public Optional<ObjectiveContext> context() {
        return context;
    }

    @Override
    public TrafficSelector meta() {
        return meta;
    }

    @Override
    public int hashCode() {
        return Objects.hash(treatments, appId, type, id, op, meta);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj instanceof DefaultNextObjective) {
            final DefaultNextObjective other = (DefaultNextObjective) obj;
            return Objects.equals(this.treatments, other.treatments)
                    && Objects.equals(this.appId, other.appId)
                    && Objects.equals(this.type, other.type)
                    && Objects.equals(this.id, other.id)
                    && Objects.equals(this.op, other.op)
                    && Objects.equals(this.meta, other.meta);
        }
        return false;
    }

    @Override
    public String toString() {
        return toStringHelper(this)
                .add("id", id())
                .add("type", type())
                .add("op", op())
                .add("priority", priority())
                .add("next", next())
                .add("meta", meta())
                .add("appId", appId())
                .add("permanent", permanent())
                .add("timeout", timeout())
                .add("context", context())
                .toString();
    }

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

    @Override
    public Builder copy() {
        return new Builder(this);
    }

    public static final class Builder implements NextObjective.Builder {

        private ApplicationId appId;
        private Type type;
        private Integer id;
        private List<TrafficTreatment> treatments;
        private Operation op;
        private ObjectiveContext context;
        private TrafficSelector meta;

        private final ImmutableList.Builder<TrafficTreatment> listBuilder
                = ImmutableList.builder();

        // Creates an empty builder
        private Builder() {
        }

        // Creates a builder set to create a copy of the specified objective.
        private Builder(NextObjective objective) {
            this.type = objective.type();
            this.id = objective.id();
            this.treatments = ImmutableList.copyOf(objective.next());
            this.listBuilder.addAll(objective.next());
            this.meta = objective.meta();
            this.appId = objective.appId();
            this.op = objective.op();
        }

        @Override
        public Builder withId(int nextId) {
            this.id = nextId;
            return this;
        }

        @Override
        public Builder withType(Type type) {
            this.type = type;
            return this;
        }

        @Override
        public Builder addTreatment(TrafficTreatment treatment) {
            listBuilder.add(treatment);
            return this;
        }

        /**
         * Noop. This method has no effect.
         *
         * @param timeout a timeout
         * @return a next objective builder
         */
        @Override
        public Builder makeTemporary(int timeout) {
            return this;
        }

        /**
         * Noop. This method has no effect.
         *
         * @return a next objective builder
         */
        @Override
        public Builder makePermanent() {
            return this;
        }

        @Override
        public Builder fromApp(ApplicationId appId) {
            this.appId = appId;
            return this;
        }

        /**
         * Noop. This method has no effect.
         *
         * @param priority an integer
         * @return a next objective builder
         */
        @Override
        public Builder withPriority(int priority) {
            return this;
        }

        @Override
        public Builder withMeta(TrafficSelector meta) {
            this.meta = meta;
            return this;
        }

        @Override
        public NextObjective add() {
            treatments = listBuilder.build();
            op = Operation.ADD;
            checkNotNull(appId, "Must supply an application id");
            checkNotNull(id, "id cannot be null");
            checkNotNull(type, "The type cannot be null");
            checkArgument(!treatments.isEmpty(), "Must have at least one treatment");

            return new DefaultNextObjective(this);
        }

        @Override
        public NextObjective remove() {
            treatments = listBuilder.build();
            op = Operation.REMOVE;
            checkNotNull(appId, "Must supply an application id");
            checkNotNull(id, "id cannot be null");
            checkNotNull(type, "The type cannot be null");

            return new DefaultNextObjective(this);
        }

        @Override
        public NextObjective add(ObjectiveContext context) {
            treatments = listBuilder.build();
            op = Operation.ADD;
            this.context = context;
            checkNotNull(appId, "Must supply an application id");
            checkNotNull(id, "id cannot be null");
            checkNotNull(type, "The type cannot be null");
            checkArgument(!treatments.isEmpty(), "Must have at least one treatment");

            return new DefaultNextObjective(this);
        }

        @Override
        public NextObjective remove(ObjectiveContext context) {
            treatments = listBuilder.build();
            op = Operation.REMOVE;
            this.context = context;
            checkNotNull(appId, "Must supply an application id");
            checkNotNull(id, "id cannot be null");
            checkNotNull(type, "The type cannot be null");

            return new DefaultNextObjective(this);
        }

        @Override
        public NextObjective addToExisting() {
            treatments = listBuilder.build();
            op = Operation.ADD_TO_EXISTING;
            checkNotNull(appId, "Must supply an application id");
            checkNotNull(id, "id cannot be null");
            checkNotNull(type, "The type cannot be null");
            checkArgument(!treatments.isEmpty(), "Must have at least one treatment");

            return new DefaultNextObjective(this);
        }

        @Override
        public NextObjective removeFromExisting() {
            treatments = listBuilder.build();
            op = Operation.REMOVE_FROM_EXISTING;
            checkNotNull(appId, "Must supply an application id");
            checkNotNull(id, "id cannot be null");
            checkNotNull(type, "The type cannot be null");

            return new DefaultNextObjective(this);
        }

        @Override
        public NextObjective addToExisting(ObjectiveContext context) {
            treatments = listBuilder.build();
            op = Operation.ADD_TO_EXISTING;
            this.context = context;
            checkNotNull(appId, "Must supply an application id");
            checkNotNull(id, "id cannot be null");
            checkNotNull(type, "The type cannot be null");
            checkArgument(!treatments.isEmpty(), "Must have at least one treatment");

            return new DefaultNextObjective(this);
        }

        @Override
        public NextObjective removeFromExisting(ObjectiveContext context) {
            treatments = listBuilder.build();
            op = Operation.REMOVE_FROM_EXISTING;
            this.context = context;
            checkNotNull(appId, "Must supply an application id");
            checkNotNull(id, "id cannot be null");
            checkNotNull(type, "The type cannot be null");

            return new DefaultNextObjective(this);
        }

    }

}
