/*
 * 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 com.google.common.annotations.Beta;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.IdGenerator;
import org.onosproject.net.NetworkResource;

import java.util.Collection;
import java.util.Objects;

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

/**
 * Abstraction of an application level intent.
 * <p>
 * Make sure that an Intent should be immutable when a new type is defined.
 * </p>
 */
@Beta
public abstract class Intent {

    private final IntentId id;

    private final ApplicationId appId;
    private final Key key;

    private final int priority;
    public static final int DEFAULT_INTENT_PRIORITY = 100;
    public static final int MAX_PRIORITY = (1 << 16) - 1;
    public static final int MIN_PRIORITY = 1;

    private final Collection<NetworkResource> resources;

    private static IdGenerator idGenerator;

    /**
     * Constructor for serializer.
     */
    protected Intent() {
        this.id = null;
        this.appId = null;
        this.key = null;
        this.resources = null;
        this.priority = DEFAULT_INTENT_PRIORITY;
    }

    /**
     * Creates a new intent.
     *
     * @param appId     application identifier
     * @param key       optional key
     * @param resources required network resources (optional)
     * @param priority  flow rule priority
     */
    protected Intent(ApplicationId appId,
                     Key key,
                     Collection<NetworkResource> resources,
                     int priority) {
        checkState(idGenerator != null, "Id generator is not bound.");
        checkArgument(priority <= MAX_PRIORITY && priority >= MIN_PRIORITY);
        this.id = IntentId.valueOf(idGenerator.getNewId());
        this.appId = checkNotNull(appId, "Application ID cannot be null");
        this.key = (key != null) ? key : Key.of(id.fingerprint(), appId);
        this.priority = priority;
        this.resources = checkNotNull(resources);
    }

    /**
     * Abstract builder for intents.
     */
    public abstract static class Builder {
        protected ApplicationId appId;
        protected Key key;
        protected int priority = Intent.DEFAULT_INTENT_PRIORITY;
        protected Collection<NetworkResource> resources;

        /**
         * Creates a new empty builder.
         */
        protected Builder() {
        }

        /**
         * Creates a new builder pre-populated with the information in the given
         * intent.
         *
         * @param intent initial intent
         */
        protected Builder(Intent intent) {
            this.appId(intent.appId())
                    .key(intent.key())
                    .priority(intent.priority());
        }

        /**
         * Sets the application id for the intent that will be built.
         *
         * @param appId application id to use for built intent
         * @return this builder
         */
        public Builder appId(ApplicationId appId) {
            this.appId = appId;
            return this;
        }

        /**
         * Sets the key for the intent that will be built.
         *
         * @param key key to use for built intent
         * @return this builder
         */
        public Builder key(Key key) {
            this.key = key;
            return this;
        }

        /**
         * Sets the priority for the intent that will be built.
         *
         * @param priority priority to use for built intent
         * @return this builder
         */
        public Builder priority(int priority) {
            this.priority = priority;
            return this;
        }

        /**
         * Sets the collection of resources required for this intent.
         *
         * @param resources collection of resources
         * @return this builder
         */
        public Builder resources(Collection<NetworkResource> resources) {
            this.resources = resources;
            return this;
        }
    }

    /**
     * Returns the intent identifier.
     *
     * @return intent fingerprint
     */
    public IntentId id() {
        return id;
    }

    /**
     * Returns the identifier of the application that requested the intent.
     *
     * @return application identifier
     */
    public ApplicationId appId() {
        return appId;
    }

    /**
     * Returns the priority of the intent.
     *
     * @return intent priority
     */
    public int priority() {
        return priority;
    }

    /**
     * Returns the collection of resources required for this intent.
     *
     * @return collection of resources; may be null
     */
    public Collection<NetworkResource> resources() {
        return resources;
    }

    /**
     * Indicates whether or not the intent is installable.
     *
     * @return true if installable
     */
    public boolean isInstallable() {
        return false;
    }

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

    @Override
    public final boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null || getClass() != obj.getClass()) {
            return false;
        }
        final Intent other = (Intent) obj;
        return this.id().equals(other.id());
    }

    /**
     * Binds an id generator for unique intent id generation.
     *
     * Note: A generator cannot be bound if there is already a generator bound.
     *
     * @param newIdGenerator id generator
     */
    public static void bindIdGenerator(IdGenerator newIdGenerator) {
        checkState(idGenerator == null, "Id generator is already bound.");
        idGenerator = checkNotNull(newIdGenerator);
    }

    /**
     * Unbinds an id generator.
     *
     * Note: The caller must provide the old id generator to succeed.
     *
     * @param oldIdGenerator the current id generator
     */
    public static void unbindIdGenerator(IdGenerator oldIdGenerator) {
        if (Objects.equals(idGenerator, oldIdGenerator)) {
            idGenerator = null;
        }
    }

    public Key key() {
        return key;
    }
}
