/*
 * 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.provider.tl1.device.impl;

import com.google.common.collect.ImmutableList;
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.onlab.packet.ChassisId;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.incubator.net.config.basics.ConfigException;
import org.onosproject.net.AnnotationKeys;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.MastershipRole;
import org.onosproject.net.PortNumber;
import org.onosproject.net.SparseAnnotations;
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.basics.SubjectFactories;
import org.onosproject.net.device.DefaultDeviceDescription;
import org.onosproject.net.device.DeviceAdminService;
import org.onosproject.net.device.DeviceDescription;
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.provider.AbstractProvider;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.tl1.DefaultTl1Device;
import org.onosproject.tl1.Tl1Controller;
import org.onosproject.tl1.Tl1Device;
import org.onosproject.tl1.Tl1Listener;
import org.onosproject.tl1.device.Tl1DeviceConfig;
import org.slf4j.Logger;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Set;

import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Device provider for TL1 devices.
 * <p>
 * Sits between ONOS provider service and the TL1 controller.
 * Relies on network config subsystem to know about devices.
 */
@Component(immediate = true)
public class Tl1DeviceProvider extends AbstractProvider implements DeviceProvider {
    private static final String APP_NAME = "org.onosproject.tl1";
    /**
     * @deprecated in 1.11.0. Use {@link Tl1DeviceConfig#TL1} instead
     */
    @Deprecated
    protected static final String TL1 = Tl1DeviceConfig.TL1;
    private static final String PROVIDER = "org.onosproject.provider.tl1.device";
    private static final String UNKNOWN = "unknown";
    private static final int REACHABILITY_TIMEOUT = 2000;      // in milliseconds

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

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected CoreService coreService;

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected DeviceAdminService deviceAdminService;

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected Tl1Controller controller;

    private ApplicationId appId;
    private NetworkConfigListener cfgListener = new InnerConfigListener();
    private Tl1Listener tl1Listener = new InnerTl1Listener();
    private DeviceProviderService providerService;

    private final List<ConfigFactory> factories = ImmutableList.of(
            new ConfigFactory<ApplicationId, Tl1ProviderConfig>(APP_SUBJECT_FACTORY,
                                                                Tl1ProviderConfig.class,
                                                                "tl1_devices",
                                                                true) {
                @Override
                public Tl1ProviderConfig createConfig() {
                    return new Tl1ProviderConfig();
                }
            },
            new ConfigFactory<DeviceId, Tl1DeviceConfig>(SubjectFactories.DEVICE_SUBJECT_FACTORY,
                                                         Tl1DeviceConfig.class,
                                                         Tl1DeviceConfig.TL1) {
                @Override
                public Tl1DeviceConfig createConfig() {
                    return new Tl1DeviceConfig();
                }
            });

    @Activate
    public void activate() {
        appId = coreService.registerApplication(APP_NAME);
        providerService = providerRegistry.register(this);
        cfgRegistry.addListener(cfgListener);
        controller.addListener(tl1Listener);
        factories.forEach(cfgRegistry::registerConfigFactory);
        registerDevices();
        connectDevices();
        log.info("Started");
    }

    @Deactivate
    public void deactivate() {
        controller.removeListener(tl1Listener);
        cfgRegistry.removeListener(cfgListener);
        controller.getDeviceIds().forEach(deviceId -> {
            controller.removeDevice(deviceId);
            deviceAdminService.removeDevice(deviceId);
        });
        providerRegistry.unregister(this);
        factories.forEach(cfgRegistry::unregisterConfigFactory);
        providerService = null;
        log.info("Stopped");
    }

    public Tl1DeviceProvider() {
        super(new ProviderId(Tl1DeviceConfig.TL1, PROVIDER));
    }

    @Override
    public void triggerProbe(DeviceId deviceId) {
        // TODO
    }

    @Override
    public void roleChanged(DeviceId deviceId, MastershipRole newRole) {
        switch (newRole) {
            case MASTER:
                controller.connectDevice(deviceId);
                providerService.receivedRoleReply(deviceId, newRole, MastershipRole.MASTER);
                log.debug("Accepting mastership role change to {} for device {}", newRole, deviceId);
                break;
            case STANDBY:
                controller.disconnectDevice(deviceId);
                providerService.receivedRoleReply(deviceId, newRole, MastershipRole.STANDBY);
                break;
            case NONE:
                controller.disconnectDevice(deviceId);
                providerService.receivedRoleReply(deviceId, newRole, MastershipRole.NONE);
                break;
            default:
                log.error("Invalid mastership state: {}", newRole);
        }
    }

    // Assumes device is registered in TL1 controller.
    @Override
    public boolean isReachable(DeviceId deviceId) {
        try {
            // First check if device is already connected.
            // If not, try to open a socket.
            Tl1Device device = controller.getDevice(deviceId).get();
            if (device.isConnected()) {
                return true;
            }

            Socket socket = new Socket();
            socket.connect(new InetSocketAddress(device.ip().toInetAddress(), device.port()), REACHABILITY_TIMEOUT);
            socket.close();
            return true;
        } catch (NoSuchElementException | IOException | IllegalArgumentException e) {
            log.error("Cannot reach device {}", deviceId, e);
            return false;
        }
    }

    @Override
    public void changePortState(DeviceId deviceId, PortNumber portNumber, boolean enable) {
        // TODO
    }

    //Old method to register devices provided via net-cfg under apps/tl1/ tree
    void registerDevices() {
        Tl1ProviderConfig cfg = cfgRegistry.getConfig(appId, Tl1ProviderConfig.class);

        if (cfg == null) {
            return;
        }

        try {
            cfg.readDevices().forEach(this::connectDevice);
        } catch (ConfigException e) {
            log.error("Cannot parse network configuration", e);
        }
    }

    //Method to register devices provided via net-cfg under devices/ tree
    private void connectDevices() {
        Set<DeviceId> deviceSubjects =
                cfgRegistry.getSubjects(DeviceId.class, Tl1DeviceConfig.class);
        deviceSubjects.forEach(deviceId -> {
            Tl1DeviceConfig config =
                    cfgRegistry.getConfig(deviceId, Tl1DeviceConfig.class);
            connectDevice(new DefaultTl1Device(config.ip(), config.port(), config.username(),
                                               config.password()));
        });
    }

    // Register a device in the core and in the TL1 controller.
    private void connectDevice(Tl1Device device) {
        try {
            // Add device to TL1 controller
            DeviceId deviceId = DeviceId.deviceId(
                    new URI(Tl1DeviceConfig.TL1, device.ip() + ":" + device.port(), null));

            if (controller.addDevice(deviceId, device)) {
                SparseAnnotations ann = DefaultAnnotations.builder()
                        .set(AnnotationKeys.PROTOCOL, Tl1DeviceConfig.TL1.toUpperCase())
                        .build();
                // Register device in the core with default parameters and mark it as unavailable
                DeviceDescription dd = new DefaultDeviceDescription(deviceId.uri(),
                                                                    Device.Type.SWITCH,
                                                                    UNKNOWN, UNKNOWN,
                                                                    UNKNOWN, UNKNOWN,
                                                                    new ChassisId(),
                                                                    false, ann);
                providerService.deviceConnected(deviceId, dd);
            }
        } catch (URISyntaxException e) {
            log.error("Skipping device {}", device, e);
        }
    }

    /**
     * Tries to update the device and port descriptions through the {@code DeviceDescriptionDiscovery} behaviour.
     *
     * @param deviceId the device
     */
    void updateDevice(DeviceId deviceId) {
        Device device = deviceService.getDevice(deviceId);

        if (!device.is(DeviceDescriptionDiscovery.class)) {
            return;
        }

        try {
            // Update device description
            DeviceDescriptionDiscovery discovery = device.as(DeviceDescriptionDiscovery.class);
            DeviceDescription dd = discovery.discoverDeviceDetails();
            if (dd == null) {
                return;
            }
            providerService.deviceConnected(deviceId,
                                            new DefaultDeviceDescription(dd, true, dd.annotations()));
            // Update ports
            providerService.updatePorts(deviceId, discovery.discoverPortDetails());
        } catch (IllegalStateException | IllegalArgumentException e) {
            log.error("Cannot update device description {}", deviceId, e);
        }
    }

    /**
     * Listener for network configuration events.
     */
    private class InnerConfigListener implements NetworkConfigListener {
        @Override
        public void event(NetworkConfigEvent event) {
            if (event.type() == NetworkConfigEvent.Type.CONFIG_ADDED) {
                if (event.configClass().equals(Tl1DeviceConfig.class)) {
                    connectDevices();
                } else {
                    log.warn("Injecting device via this Json is deprecated, " +
                                     "please put configuration under devices/");
                    registerDevices();
                }
            } else if (event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED) {
                // TODO: calculate delta
                if (event.configClass().equals(Tl1DeviceConfig.class)) {
                    connectDevices();
                } else {
                    log.warn("Injecting device via this Json is deprecated, " +
                                     "please put configuration under devices/");
                    registerDevices();
                }
            } else if (event.type() == NetworkConfigEvent.Type.CONFIG_REMOVED) {
                controller.getDeviceIds().forEach(deviceId -> {
                    controller.removeDevice(deviceId);
                    deviceAdminService.removeDevice(deviceId);
                });
            }
        }

        @Override
        public boolean isRelevant(NetworkConfigEvent event) {
            return (event.configClass().equals(Tl1DeviceConfig.class) ||
                    event.configClass().equals(Tl1ProviderConfig.class)) &&
                    (event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
                            event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED ||
                            event.type() == NetworkConfigEvent.Type.CONFIG_REMOVED);
        }
    }

    /**
     * Listener for TL1 events.
     */
    private class InnerTl1Listener implements Tl1Listener {
        @Override
        public void deviceConnected(DeviceId deviceId) {
            updateDevice(deviceId);
        }

        @Override
        public void deviceDisconnected(DeviceId deviceId) {
            providerService.deviceDisconnected(deviceId);
        }
    }
}
