/*
 * 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.config.impl;

import static java.util.concurrent.Executors.newSingleThreadExecutor;
import static org.onlab.util.Tools.groupedThreads;
import static org.onosproject.net.PortNumber.portNumber;
import static org.onosproject.net.config.basics.SubjectFactories.DEVICE_SUBJECT_FACTORY;
import static org.slf4j.LoggerFactory.getLogger;

import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;

import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onlab.packet.ChassisId;
import org.onosproject.net.Device.Type;
import org.onosproject.net.DeviceId;
import org.onosproject.net.MastershipRole;
import org.onosproject.net.PortNumber;
import org.onosproject.net.config.ConfigFactory;
import org.onosproject.net.config.NetworkConfigEvent;
import org.onosproject.net.config.NetworkConfigListener;
import org.onosproject.net.config.NetworkConfigRegistry;
import org.onosproject.net.config.NetworkConfigService;
import org.onosproject.net.config.basics.BasicDeviceConfig;
import org.onosproject.net.config.inject.DeviceInjectionConfig;
import org.onosproject.net.device.DefaultDeviceDescription;
import org.onosproject.net.device.DefaultPortDescription;
import org.onosproject.net.device.DeviceDescriptionDiscovery;
import org.onosproject.net.device.DeviceProvider;
import org.onosproject.net.device.DeviceProviderRegistry;
import org.onosproject.net.device.DeviceProviderService;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.device.PortDescription;
import org.onosproject.net.driver.DefaultDriverData;
import org.onosproject.net.driver.DefaultDriverHandler;
import org.onosproject.net.driver.DriverService;
import org.onosproject.net.provider.ProviderId;
import org.slf4j.Logger;

import com.google.common.annotations.Beta;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;

// TODO In theory just @Component should be sufficient,
//      but won't work without @Service. Need investigation.
/**
 * Component to monitor DeviceInjectionConfig changes.
 */
@Beta
@Service(value = DeviceInjectionConfigMonitor.class)
@Component(immediate = true)
public class DeviceInjectionConfigMonitor {

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

    private final ProviderId pid = new ProviderId("inject", "org.onosproject.inject");

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected NetworkConfigService netcfgService;

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected DeviceProviderRegistry deviceProviderRegistry;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected DriverService driverService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected NetworkConfigRegistry netcfgRegistry;

    private final List<ConfigFactory<?, ?>> factories = ImmutableList.of(
         new ConfigFactory<DeviceId, DeviceInjectionConfig>(DEVICE_SUBJECT_FACTORY,
                 DeviceInjectionConfig.class,
                 DeviceInjectionConfig.CONFIG_KEY) {
             @Override
             public DeviceInjectionConfig createConfig() {
                 return new DeviceInjectionConfig();
             }
         });


    private final InternalConfigListener listener = new InternalConfigListener();

    private ExecutorService worker;

    private InternalDeviceProvider deviceProvider = new InternalDeviceProvider();

    private DeviceProviderService providerService;


    @Activate
    public void activate() {
        worker = newSingleThreadExecutor(groupedThreads("onos/inject",
                                                        "worker",
                                                        log));
        providerService = deviceProviderRegistry.register(deviceProvider);

        netcfgService.addListener(listener);

        factories.forEach(netcfgRegistry::registerConfigFactory);

        log.info("Started");
    }

    @Deactivate
    public void deactivate() {
        netcfgService.removeListener(listener);

        deviceProviderRegistry.unregister(deviceProvider);

        worker.shutdown();
        try {
            worker.awaitTermination(5, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            log.warn("Interrupted.", e);
            Thread.currentThread().interrupt();
        }
        factories.forEach(netcfgRegistry::unregisterConfigFactory);

        log.info("Stopped");
    }

    private void removeDevice(DeviceId did) {
        providerService.deviceDisconnected(did);
    }

    private void injectDevice(DeviceId did) {
        Optional<BasicDeviceConfig> basic =
                Optional.ofNullable(netcfgService.getConfig(did, BasicDeviceConfig.class));
        Optional<DeviceDescriptionDiscovery> discovery = basic
            .map(BasicDeviceConfig::driver)
            .map(driverService::getDriver)
            .filter(drvr -> drvr.hasBehaviour(DeviceDescriptionDiscovery.class))
            .map(drvr -> drvr.createBehaviour(new DefaultDriverHandler(new DefaultDriverData(drvr, did)),
                                              DeviceDescriptionDiscovery.class));

        if (discovery.isPresent()) {
            providerService.deviceConnected(did,
                                            discovery.get().discoverDeviceDetails());
            providerService.updatePorts(did,
                                        discovery.get().discoverPortDetails());
        } else {

            String unk = "UNKNOWN";
            DefaultDeviceDescription desc = new DefaultDeviceDescription(
                     did.uri(),
                     basic.map(BasicDeviceConfig::type).orElse(Type.SWITCH),
                     basic.map(BasicDeviceConfig::manufacturer).orElse(unk),
                     basic.map(BasicDeviceConfig::hwVersion).orElse(unk),
                     basic.map(BasicDeviceConfig::swVersion).orElse(unk),
                     basic.map(BasicDeviceConfig::serial).orElse(unk),
                     new ChassisId(),
                     true);
            providerService.deviceConnected(did, desc);

            Optional<DeviceInjectionConfig> inject =
                Optional.ofNullable(netcfgService.getConfig(did, DeviceInjectionConfig.class));

            String ports = inject.map(DeviceInjectionConfig::ports).orElse("0");
            int numPorts = Integer.parseInt(ports);
            List<PortDescription> portDescs = new ArrayList<>(numPorts);
            for (int i = 1; i <= numPorts; ++i) {
                // TODO inject port details if something like BasicPortConfig was created
                PortNumber number = portNumber(i);
                boolean isEnabled = true;
                portDescs.add(new DefaultPortDescription(number, isEnabled));
            }
            providerService.updatePorts(did, portDescs);
        }
    }

    final class InternalDeviceProvider implements DeviceProvider {
        @Override
        public ProviderId id() {
            return pid;
        }

        @Override
        public void triggerProbe(DeviceId deviceId) {
            worker.execute(() -> injectDevice(deviceId));
        }

        @Override
        public void roleChanged(DeviceId deviceId, MastershipRole newRole) {
            providerService.receivedRoleReply(deviceId, newRole, newRole);
        }

        @Override
        public boolean isReachable(DeviceId deviceId) {
            return true;
        }

        @Override
        public void changePortState(DeviceId deviceId, PortNumber portNumber,
                                    boolean enable) {
            // TODO handle request to change port state from controller
        }
    }

    /**
     * Listens for Config updates.
     */
    final class InternalConfigListener
            implements NetworkConfigListener {

        /**
         * Relevant {@link NetworkConfigEvent} type.
         */
        private final Set<NetworkConfigEvent.Type> relevant
            = ImmutableSet.copyOf(EnumSet.of(
                         NetworkConfigEvent.Type.CONFIG_ADDED,
                         NetworkConfigEvent.Type.CONFIG_UPDATED,
                         NetworkConfigEvent.Type.CONFIG_REMOVED));

        @Override
        public boolean isRelevant(NetworkConfigEvent event) {
            return event.configClass() == DeviceInjectionConfig.class &&
                    relevant.contains(event.type());
        }

        @Override
        public void event(NetworkConfigEvent event) {
            worker.execute(() -> processEvent(event));
        }

        /**
         * Process Config add/update/remove event.
         * <p>
         * Note: will be executed in the worker thread.
         *
         * @param event add/update/remove event
         */
        protected void processEvent(NetworkConfigEvent event) {

            DeviceId did = (DeviceId) event.subject();
            if (!did.uri().getScheme().equals(pid.scheme())) {
                log.warn("Attempt to inject unexpected scheme {}", did);
                return;
            }
            log.debug("{} to {}: {}", event.type(), did, event);

            // TODO if there's exist one probably better to follow master
//            if (deviceService.getRole(did) != MastershipRole.MASTER) {
//                log.debug("Not the master, ignoring. {}", event);
//                return;
//            }

            switch (event.type()) {
            case CONFIG_ADDED:
            case CONFIG_UPDATED:
                injectDevice(did);
                break;
            case CONFIG_REMOVED:
                removeDevice(did);
                break;

            case CONFIG_REGISTERED:
            case CONFIG_UNREGISTERED:
            default:
                log.warn("Ignoring unexpected event: {}", event);
                break;
            }
        }
    }

}
