/*
 * Copyright 2015 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.provider.snmp.device.impl;

import com.btisystems.pronx.ems.core.snmp.DefaultSnmpConfigurationFactory;
import com.btisystems.pronx.ems.core.snmp.ISnmpConfiguration;
import com.btisystems.pronx.ems.core.snmp.ISnmpConfigurationFactory;
import com.btisystems.pronx.ems.core.snmp.ISnmpSession;
import com.btisystems.pronx.ems.core.snmp.ISnmpSessionFactory;
import com.btisystems.pronx.ems.core.snmp.SnmpSessionFactory;
import com.btisystems.pronx.ems.core.snmp.V2cSnmpConfiguration;
import static com.google.common.base.Strings.isNullOrEmpty;
import java.io.IOException;
import static org.onlab.util.Tools.delay;
import static org.onlab.util.Tools.get;
import static org.onlab.util.Tools.groupedThreads;
import static org.slf4j.LoggerFactory.getLogger;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
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.Modified;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.packet.ChassisId;
import org.onosproject.cfg.ComponentConfigService;
import org.onosproject.cluster.ClusterService;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.MastershipRole;
import org.onosproject.net.device.DefaultDeviceDescription;
import org.onosproject.net.device.DeviceDescription;
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.osgi.service.component.ComponentContext;
import org.slf4j.Logger;

/**
 * Provider which will try to fetch the details of SNMP devices from the core and run a capability discovery on each of
 * the device.
 */
@Component(immediate = true)
public class SnmpDeviceProvider extends AbstractProvider
        implements DeviceProvider {

    private final Logger log = getLogger(SnmpDeviceProvider.class);

    private static final String UNKNOWN = "unknown";

    protected Map<DeviceId, SnmpDevice> snmpDeviceMap = new ConcurrentHashMap<>();

    private DeviceProviderService providerService;

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

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected ClusterService clusterService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected ComponentConfigService cfgService;

    private final ExecutorService deviceBuilder = Executors
            .newFixedThreadPool(1, groupedThreads("onos/snmp", "device-creator"));

    // Delay between events in ms.
    private static final int EVENTINTERVAL = 5;

    private static final String SCHEME = "snmp";

    @Property(name = "devConfigs", value = "", label = "Instance-specific configurations")
    private String devConfigs = null;

    @Property(name = "devPasswords", value = "", label = "Instance-specific password")
    private String devPasswords = null;

    //TODO Could be replaced with a service lookup, and bundles per device variant.
    Map<String, SnmpDeviceDescriptionProvider> providers = new HashMap<>();

    private final ISnmpSessionFactory sessionFactory;

    /**
     * Creates a provider with the supplier identifier.
     */
    public SnmpDeviceProvider() {
        super(new ProviderId("snmp", "org.onosproject.provider.device"));
        sessionFactory = new SnmpSessionFactory(
                new DefaultSnmpConfigurationFactory(new V2cSnmpConfiguration()));
        providers.put("1.3.6.1.4.1.18070.2.2", new Bti7000DeviceDescriptionProvider());
        providers.put("1.3.6.1.4.1.20408", new NetSnmpDeviceDescriptionProvider());
    }

    @Activate
    public void activate(ComponentContext context) {
        log.info("activating for snmp devices ...");
        cfgService.registerProperties(getClass());
        providerService = providerRegistry.register(this);
        modified(context);
        log.info("activated ok");
    }

    @Deactivate
    public void deactivate(ComponentContext context) {

        log.info("deactivating for snmp devices ...");

        cfgService.unregisterProperties(getClass(), false);
        try {
            snmpDeviceMap
                    .entrySet().stream().forEach((deviceEntry) -> {
                        deviceBuilder.submit(new DeviceCreator(deviceEntry.getValue(), false));
                    });
            deviceBuilder.awaitTermination(1000, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            log.error("Device builder did not terminate");
        }
        deviceBuilder.shutdownNow();
        snmpDeviceMap.clear();
        providerRegistry.unregister(this);
        providerService = null;
        log.info("Stopped");
    }

    @Modified
    public void modified(ComponentContext context) {
        log.info("modified ...");

        if (context == null) {
            log.info("No configuration file");
            return;
        }
        Dictionary<?, ?> properties = context.getProperties();

        log.info("properties={}", context.getProperties());

        String deviceCfgValue = get(properties, "devConfigs");
        log.info("Settings: devConfigs={}", deviceCfgValue);
        if (!isNullOrEmpty(deviceCfgValue)) {
            addOrRemoveDevicesConfig(deviceCfgValue);
        }
        log.info("... modified");

    }

    private void addOrRemoveDevicesConfig(String deviceConfig) {
        for (String deviceEntry : deviceConfig.split(",")) {
            SnmpDevice device = processDeviceEntry(deviceEntry);
            if (device != null) {
                log.info("Device Detail:host={}, port={}, state={}",
                        new Object[]{device.getSnmpHost(),
                            device.getSnmpPort(),
                            device.getDeviceState().name()}
                );
                if (device.isActive()) {
                    deviceBuilder.submit(new DeviceCreator(device, true));
                } else {
                    deviceBuilder.submit(new DeviceCreator(device, false));
                }
            }
        }
    }

    private SnmpDevice processDeviceEntry(String deviceEntry) {
        if (deviceEntry == null) {
            log.info("No content for Device Entry, so cannot proceed further.");
            return null;
        }
        log.info("Trying to convert {} to a SNMP Device Object", deviceEntry);
        SnmpDevice device = null;
        try {
            String userInfo = deviceEntry.substring(0, deviceEntry
                    .lastIndexOf('@'));
            String hostInfo = deviceEntry.substring(deviceEntry
                    .lastIndexOf('@') + 1);
            String[] infoSplit = userInfo.split(":");
            String username = infoSplit[0];
            String password = infoSplit[1];
            infoSplit = hostInfo.split(":");
            String hostIp = infoSplit[0];
            Integer hostPort;
            try {
                hostPort = Integer.parseInt(infoSplit[1]);
            } catch (NumberFormatException nfe) {
                log.error("Bad Configuration Data: Failed to parse host port number string: "
                        + infoSplit[1]);
                throw nfe;
            }
            String deviceState = infoSplit[2];
            if (isNullOrEmpty(username) || isNullOrEmpty(password)
                    || isNullOrEmpty(hostIp) || hostPort == 0) {
                log.warn("Bad Configuration Data: both user and device information parts of Configuration "
                        + deviceEntry + " should be non-nullable");
            } else {
                device = new SnmpDevice(hostIp, hostPort, password);
                if (!isNullOrEmpty(deviceState)) {
                    if (deviceState.toUpperCase().equals(DeviceState.ACTIVE.name())) {
                        device.setDeviceState(DeviceState.ACTIVE);
                    } else if (deviceState.toUpperCase()
                            .equals(DeviceState.INACTIVE.name())) {
                        device.setDeviceState(DeviceState.INACTIVE);
                    } else {
                        log.warn("Device State Information can not be empty, so marking the state as INVALID");
                        device.setDeviceState(DeviceState.INVALID);
                    }
                } else {
                    log.warn("The device entry do not specify state information, so marking the state as INVALID");
                    device.setDeviceState(DeviceState.INVALID);
                }
            }
        } catch (ArrayIndexOutOfBoundsException aie) {
            log.error("Error while reading config infromation from the config file: "
                    + "The user, host and device state infomation should be "
                    + "in the order 'userInfo@hostInfo:deviceState'"
                    + deviceEntry, aie);
        } catch (Exception e) {
            log.error("Error while parsing config information for the device entry: "
                    + deviceEntry, e);
        }
        return device;
    }

    @Override
    public void triggerProbe(DeviceId deviceId) {
        // TODO SNMP devices should be polled at scheduled intervals to retrieve their
        // reachability status and other details e.g.swVersion, serialNumber,chassis,
    }

    @Override
    public void roleChanged(DeviceId deviceId, MastershipRole newRole) {

    }

    @Override
    public boolean isReachable(DeviceId deviceId) {
        SnmpDevice snmpDevice = snmpDeviceMap.get(deviceId);
        if (snmpDevice == null) {
            log.warn("BAD REQUEST: the requested device id: "
                    + deviceId.toString()
                    + "  is not associated to any SNMP Device");
            return false;
        }
        return snmpDevice.isReachable();
    }

    /**
     * This class is intended to add or remove Configured SNMP Devices. Functionality relies on 'createFlag' and
     * 'SnmpDevice' content. The functionality runs as a thread and depending on the 'createFlag' value it will create
     * or remove Device entry from the core.
     */
    private class DeviceCreator implements Runnable {

        private SnmpDevice device;
        private boolean createFlag;

        public DeviceCreator(SnmpDevice device, boolean createFlag) {
            this.device = device;
            this.createFlag = createFlag;
        }

        @Override
        public void run() {
            if (createFlag) {
                log.info("Trying to create Device Info on ONOS core");
                advertiseDevices();
            } else {
                log.info("Trying to remove Device Info on ONOS core");
                removeDevices();
            }
        }

        /**
         * For each SNMP Device, remove the entry from the device store.
         */
        private void removeDevices() {
            if (device == null) {
                log.warn("The Request SNMP Device is null, cannot proceed further");
                return;
            }
            try {
                DeviceId did = getDeviceId();
                if (!snmpDeviceMap.containsKey(did)) {
                    log.error("BAD Request: 'Currently device is not discovered, "
                            + "so cannot remove/disconnect the device: "
                            + device.deviceInfo() + "'");
                    return;
                }
                providerService.deviceDisconnected(did);
                device.disconnect();
                snmpDeviceMap.remove(did);
                delay(EVENTINTERVAL);
            } catch (URISyntaxException uriSyntaxExcpetion) {
                log.error("Syntax Error while creating URI for the device: "
                        + device.deviceInfo()
                        + " couldn't remove the device from the store",
                        uriSyntaxExcpetion);
            }
        }

        /**
         * Initialize SNMP Device object, and notify core saying device connected.
         */
        private void advertiseDevices() {
            try {
                if (device == null) {
                    log.warn("The Request SNMP Device is null, cannot proceed further");
                    return;
                }
                device.init();
                DeviceId did = getDeviceId();
                ChassisId cid = new ChassisId();


                DeviceDescription desc = new DefaultDeviceDescription(
                        did.uri(), Device.Type.OTHER, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, cid);

                desc = populateDescriptionFromDevice(did, desc);

                log.info("Persisting Device " + did.uri().toString());

                snmpDeviceMap.put(did, device);
                providerService.deviceConnected(did, desc);
                log.info("Done with Device Info Creation on ONOS core. Device Info: "
                        + device.deviceInfo() + " " + did.uri().toString());
                delay(EVENTINTERVAL);
            } catch (URISyntaxException e) {
                log.error("Syntax Error while creating URI for the device: "
                        + device.deviceInfo()
                        + " couldn't persist the device onto the store", e);
            } catch (Exception e) {
                log.error("Error while initializing session for the device: "
                        + (device != null ? device.deviceInfo() : null), e);
            }
        }

        private DeviceDescription populateDescriptionFromDevice(DeviceId did, DeviceDescription desc) {
            String[] deviceComponents = did.toString().split(":");
            if (deviceComponents.length > 1) {
                String ipAddress = deviceComponents[1];
                String port = deviceComponents[2];

           ISnmpConfiguration config = new V2cSnmpConfiguration();
            config.setPort(Integer.parseInt(port));

                try (ISnmpSession session = sessionFactory.createSession(config, ipAddress)) {
                    // Each session will be auto-closed.
                    String deviceOID = session.identifyDevice();

                    if (providers.containsKey(deviceOID)) {
                        desc = providers.get(deviceOID).populateDescription(session, desc);
                    }

                } catch (IOException | RuntimeException ex) {
                    log.error("Failed to walk device.", ex.getMessage());
                    log.debug("Detailed problem was ", ex);
                }
            }
            return desc;
        }

        /**
         * This will build a device id for the device.
         */
        private DeviceId getDeviceId() throws URISyntaxException {
            String additionalSSP = new StringBuilder(
                    device.getSnmpHost()).append(":")
                    .append(device.getSnmpPort()).toString();
            return DeviceId.deviceId(new URI(SCHEME, additionalSSP,
                    null));
        }
    }

    protected ISnmpSessionFactory getSessionFactory(ISnmpConfigurationFactory configurationFactory) {
        return new SnmpSessionFactory(configurationFactory);
    }
}
