/*
 * Copyright 2016-present Open Networking Foundation
 *
 * 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;

import com.google.common.annotations.Beta;
import org.onlab.util.ItemNotFoundException;
import org.onosproject.net.driver.Behaviour;
import org.onosproject.net.driver.Driver;
import org.onosproject.net.driver.DriverData;
import org.onosproject.net.driver.DriverService;
import org.onosproject.net.driver.Projectable;
import org.onosproject.net.provider.ProviderId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Set;

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

/**
 * Base model entity, capable of being extended via projection mechanism.
 */
@Beta
public abstract class AbstractProjectableModel extends AbstractModel implements Projectable {

    private static Logger log = LoggerFactory.getLogger(AbstractProjectableModel.class);

    protected static final String NO_DRIVER_SERVICE = "Driver service not bound yet";
    protected static final String NO_DRIVER = "Driver has not been bound to %s";

    // Static reference to the driver service; injected via setDriverService
    private static DriverService driverService;

    private transient Driver driver;

    // For serialization
    public AbstractProjectableModel() {
    }

    /**
     * Creates a model entity attributed to the specified provider and
     * optionally annotated.
     *
     * @param providerId  identity of the provider
     * @param annotations optional key/value annotations
     */
    public AbstractProjectableModel(ProviderId providerId, Annotations[] annotations) {
        super(providerId, annotations);
    }

    /**
     * Injects the driver service reference for use during projections into
     * various behaviours.
     * <p>
     * This is a privileged call; unauthorized invocations will result in
     * illegal state exception
     *
     * @param key           opaque admin key object
     * @param driverService injected driver service
     * @throws IllegalStateException when invoked sans authorization
     */
    public static void setDriverService(Object key, DriverService driverService) {
        // TODO: Rework this once we have means to enforce access to admin services in general
//        checkState(AbstractProjectableModel.driverService == key, "Unauthorized invocation");
        AbstractProjectableModel.driverService = driverService;
    }

    /**
     * Returns the currently bound driver service reference.
     *
     * @return driver service
     */
    protected static DriverService driverService() {
        return driverService;
    }

    /**
     * Returns the currently bound driver or null if no driver is bound.
     *
     * @return bound driver; null if none
     */
    public Driver driver() {
        return driver;
    }

    @Override
    public <B extends Behaviour> B as(Class<B> projectionClass) {
        bindAndCheckDriver();
        return driver.createBehaviour(asData(), projectionClass);
    }

    @Override
    public <B extends Behaviour> boolean is(Class<B> projectionClass) {
        bindDriver();
        return driver != null && driver.hasBehaviour(projectionClass);
    }

    /**
     * Locates the driver to be used by this entity.
     * <p>
     * The default implementation derives the driver based on the {@code driver}
     * annotation value.
     *
     * @return driver for alternate projections of this model entity or null
     * if no driver is expected or driver is not found
     */
    protected Driver locateDriver() {
        Annotations annotations = annotations();
        String driverName = annotations != null ? annotations.value(AnnotationKeys.DRIVER) : null;
        if (driverName != null) {
            try {
                return driverService.getDriver(driverName);
            } catch (ItemNotFoundException e) {
                log.warn("Driver {} not found.", driverName);
            }
        }
        return null;
    }

    /**
     * Attempts to binds the driver, if not already bound.
     */
    protected final void bindDriver() {
        checkState(driverService != null, NO_DRIVER_SERVICE);
        if (driver == null) {
            driver = locateDriver();
        }
    }

    /**
     * Attempts to bind the driver, if not already bound and checks that the
     * driver is bound.
     *
     * @throws IllegalStateException if driver cannot be bound
     */
    protected final void bindAndCheckDriver() {
        bindDriver();
        checkState(driver != null, NO_DRIVER, this);
    }

    /**
     * Returns self as an immutable driver data instance.
     *
     * @return self as driver data
     */
    protected DriverData asData() {
        return new AnnotationDriverData();
    }


    /**
     * Projection of the parent entity as a driver data entity.
     */
    protected class AnnotationDriverData implements DriverData {
        @Override
        public Driver driver() {
            return driver;
        }

        @Override
        public DeviceId deviceId() {
            throw new UnsupportedOperationException("Entity not a device");
        }

        @Override
        public MutableAnnotations set(String key, String value) {
            throw new UnsupportedOperationException("Entity is immutable");
        }

        @Override
        public MutableAnnotations clear(String... keys) {
            throw new UnsupportedOperationException("Entity is immutable");
        }

        @Override
        public Set<String> keys() {
            return annotations().keys();
        }

        @Override
        public String value(String key) {
            return annotations().value(key);
        }
    }

}
