/*
 * Copyright 2017-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.driver.impl;

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.onosproject.net.driver.DriverRegistry;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Modified;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.onosproject.cfg.ComponentConfigService;
import org.onosproject.component.ComponentService;
import org.onosproject.event.EventDeliveryService;
import org.onosproject.event.ListenerRegistry;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.driver.Behaviour;
import org.onosproject.net.driver.DefaultDriverProvider;
import org.onosproject.net.driver.Driver;
import org.onosproject.net.driver.DriverAdminService;
import org.onosproject.net.driver.DriverEvent;
import org.onosproject.net.driver.DriverListener;
import org.onosproject.net.driver.DriverProvider;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Dictionary;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import java.util.Set;

import static com.google.common.base.Strings.isNullOrEmpty;
import static org.onlab.util.Tools.get;
import static org.onlab.util.Tools.nullIsNotFound;
import static org.onosproject.net.driver.DriverEvent.Type.DRIVER_ENHANCED;
import static org.onosproject.net.driver.DriverEvent.Type.DRIVER_REDUCED;
import static org.onosproject.security.AppGuard.checkPermission;
import static org.onosproject.security.AppPermission.Type.DRIVER_READ;


/**
 * Manages inventory of device drivers.
 */
@Component(
    immediate = true,
    service = {
        DriverAdminService.class,
        DriverRegistry.class
    }
)
public class DriverRegistryManager extends DefaultDriverProvider implements DriverAdminService {

    private static final String DRIVER_COMPONENT = "org.onosproject.net.driver.impl.DriverManager";

    private final Logger log = LoggerFactory.getLogger(getClass());

    private static final String FORMAT = "Required drivers: {}";
    private static final String COMMA = ",";
    private static final String NO_DRIVER = "Driver not found";
    private static final String DEFAULT = "default";

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected DeviceService deviceService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected ComponentConfigService componentConfigService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected ComponentService componenService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected EventDeliveryService eventDispatcher;

    private static final String DEFAULT_REQUIRED_DRIVERS = "default";
    private static String requiredDrivers = DEFAULT_REQUIRED_DRIVERS;
    private Set<String> requiredDriverSet;

    private Set<DriverProvider> providers = Sets.newConcurrentHashSet();
    private Map<String, Driver> driverByKey = Maps.newConcurrentMap();
    private Map<String, Class<? extends Behaviour>> classes = Maps.newConcurrentMap();

    private ListenerRegistry<DriverEvent, DriverListener> listenerRegistry;


    private boolean isStarted = false;

    @Activate
    protected void activate(ComponentContext context) {
        componentConfigService.registerProperties(getClass());
        listenerRegistry = new ListenerRegistry<>();
        eventDispatcher.addSink(DriverEvent.class, listenerRegistry);
        modified(context);
        log.info("Started");
    }

    @Deactivate
    protected void deactivate() {
        componentConfigService.unregisterProperties(getClass(), false);
        eventDispatcher.removeSink(DriverEvent.class);
        providers.clear();
        driverByKey.clear();
        classes.clear();
        log.info("Stopped");
    }

    @Modified
    public void modified(ComponentContext context) {
        Dictionary<?, ?> properties = context != null ? context.getProperties() : new Properties();
        if (context != null) {
            requiredDrivers = get(properties, "requiredDrivers");
        }
        requiredDriverSet = isNullOrEmpty(requiredDrivers) ?
                ImmutableSet.of() : ImmutableSet.copyOf(requiredDrivers.split(COMMA));
        log.info(FORMAT, requiredDrivers);
        checkRequiredDrivers();
    }

    @Override
    public Set<DriverProvider> getProviders() {
        return ImmutableSet.copyOf(providers);
    }

    @Override
    public void registerProvider(DriverProvider provider) {
        provider.getDrivers().forEach(driver -> {
            Driver d = addDriver(driver);
            driverByKey.put(key(driver.manufacturer(),
                                driver.hwVersion(),
                                driver.swVersion()), d);
            d.behaviours().forEach(b -> {
                Class<? extends Behaviour> implementation = d.implementation(b);
                classes.put(b.getName(), b);
                classes.put(implementation.getName(), implementation);
            });
            post(new DriverEvent(DRIVER_ENHANCED, driver));
        });
        providers.add(provider);
        checkRequiredDrivers();
    }

    @Override
    public void unregisterProvider(DriverProvider provider) {
        provider.getDrivers().forEach(driver -> {
            removeDriver(driver);
            driverByKey.remove(key(driver.manufacturer(),
                                   driver.hwVersion(),
                                   driver.swVersion()));
            post(new DriverEvent(DRIVER_REDUCED, driver));
        });
        providers.remove(provider);
        checkRequiredDrivers();
    }

    // Checks for the minimum required drivers and when available, activate
    // the driver manager components; deactivate otherwise.
    private synchronized void checkRequiredDrivers() {
        Set<String> driverSet = registeredDrivers();
        boolean isReady = driverSet.containsAll(requiredDriverSet);
        if (isReady && !isStarted) {
            log.info("Starting driver subsystem");
            componenService.activate(null, DRIVER_COMPONENT);
            isStarted = true;
        } else if (!isReady && isStarted) {
            log.info("Stopping driver subsystem");
            componenService.deactivate(null, DRIVER_COMPONENT);
            isStarted = false;
        }
    }

    private Set<String> registeredDrivers() {
        ImmutableSet.Builder<String> builder = ImmutableSet.builder();
        for (DriverProvider dp : providers) {
            dp.getDrivers().stream().map(Driver::name).forEach(builder::add);
        }
        return builder.build();
    }

    @Override
    public Class<? extends Behaviour> getBehaviourClass(String className) {
        return classes.get(className);
    }

    @Override
    public Set<Driver> getDrivers() {
        checkPermission(DRIVER_READ);
        ImmutableSet.Builder<Driver> builder = ImmutableSet.builder();
        drivers.values().forEach(builder::add);
        return builder.build();
    }

    @Override
    public Driver getDriver(String mfr, String hw, String sw) {
        checkPermission(DRIVER_READ);

        // First attempt a literal search.
        Driver driver = driverByKey.get(key(mfr, hw, sw));
        if (driver != null) {
            return driver;
        }

        // Otherwise, sweep through the key space and attempt to match using
        // regular expression matching.
        Optional<Driver> optional = driverByKey.values().stream()
                .filter(d -> matches(d, mfr, hw, sw)).findFirst();

        // If no matching driver is found, return default.
        return optional.orElse(drivers.get(DEFAULT));
    }

    @Override
    public Driver getDriver(String driverName) {
        checkPermission(DRIVER_READ);
        return nullIsNotFound(drivers.get(driverName), NO_DRIVER);
    }

    // Matches the given driver using ERE matching against the given criteria.
    private boolean matches(Driver d, String mfr, String hw, String sw) {
        // TODO: consider pre-compiling the expressions in the future
        return mfr.matches(d.manufacturer()) &&
                hw.matches(d.hwVersion()) &&
                sw.matches(d.swVersion());
    }

    // Produces a composite driver key using the specified components.
    static String key(String mfr, String hw, String sw) {
        return String.format("%s-%s-%s", mfr, hw, sw);
    }

    @Override
    public void addListener(DriverListener listener) {
        listenerRegistry.addListener(listener);
    }

    @Override
    public void removeListener(DriverListener listener) {
        listenerRegistry.removeListener(listener);
    }

    // Safely posts the specified event to the local event dispatcher.
    private void post(DriverEvent event) {
        if (eventDispatcher != null) {
            eventDispatcher.post(event);
        }
    }

}
