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

import static com.google.common.base.Strings.isNullOrEmpty;
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.Map;
import java.util.Map.Entry;
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.onosproject.provider.netconf.device.impl.NetconfDevice.DeviceState;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;

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

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

    private Map<DeviceId, NetconfDevice> netconfDeviceMap = new ConcurrentHashMap<DeviceId, NetconfDevice>();

    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 ExecutorService deviceBuilder = Executors
            .newFixedThreadPool(1, groupedThreads("onos/netconf", "device-creator"));

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

    private static final String SCHEME = "netconf";

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

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

    /**
     * Creates a provider with the supplier identifier.
     */
    public NetconfDeviceProvider() {
        super(new ProviderId("netconf", "org.onosproject.provider.netconf"));
    }

    @Activate
    public void activate(ComponentContext context) {
        cfgService.registerProperties(getClass());
        providerService = providerRegistry.register(this);
        modified(context);
        log.info("Started");
    }

    @Deactivate
    public void deactivate(ComponentContext context) {
        cfgService.unregisterProperties(getClass(), false);
        try {
            for (Entry<DeviceId, NetconfDevice> deviceEntry : netconfDeviceMap
                    .entrySet()) {
                deviceBuilder.submit(new DeviceCreator(deviceEntry.getValue(),
                                                       false));
            }
            deviceBuilder.awaitTermination(1000, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            log.error("Device builder did not terminate");
        }
        deviceBuilder.shutdownNow();
        netconfDeviceMap.clear();
        providerRegistry.unregister(this);
        providerService = null;
        log.info("Stopped");
    }

    @Modified
    public void modified(ComponentContext context) {
        if (context == null) {
            log.info("No configuration file");
            return;
        }
        Dictionary<?, ?> properties = context.getProperties();
        String deviceCfgValue = get(properties, "devConfigs");
        log.info("Settings: devConfigs={}", deviceCfgValue);
        if (!isNullOrEmpty(deviceCfgValue)) {
            addOrRemoveDevicesConfig(deviceCfgValue);
        }
    }

    private void addOrRemoveDevicesConfig(String deviceConfig) {
        for (String deviceEntry : deviceConfig.split(",")) {
            NetconfDevice device = processDeviceEntry(deviceEntry);
            if (device != null) {
                log.info("Device Detail: username: {}, host={}, port={}, state={}",
                        device.getUsername(), device.getSshHost(),
                         device.getSshPort(), device.getDeviceState().name());
                if (device.isActive()) {
                    deviceBuilder.submit(new DeviceCreator(device, true));
                } else {
                    deviceBuilder.submit(new DeviceCreator(device, false));
                }
            }
        }
    }

    private NetconfDevice processDeviceEntry(String deviceEntry) {
        if (deviceEntry == null) {
            log.info("No content for Device Entry, so cannot proceed further.");
            return null;
        }
        log.info("Trying to convert Device Entry String: " + deviceEntry
                + " to a Netconf Device Object");
        NetconfDevice 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 NetconfDevice(hostIp, hostPort, username, 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 Auto-generated method stub
    }

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

    }

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

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

        private NetconfDevice device;
        private boolean createFlag;

        public DeviceCreator(NetconfDevice 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 Netconf Device, remove the entry from the device store.
         */
        private void removeDevices() {
            if (device == null) {
                log.warn("The Request Netconf Device is null, cannot proceed further");
                return;
            }
            try {
                DeviceId did = getDeviceId();
                if (!netconfDeviceMap.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();
                netconfDeviceMap.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 Netconf Device object, and notify core saying device
         * connected.
         */
        private void advertiseDevices() {
            try {
                if (device == null) {
                    log.warn("The Request Netconf 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,
                                                                      "", "",
                                                                      "", "",
                                                                      cid);
                log.info("Persisting Device" + did.uri().toString());

                netconfDeviceMap.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.deviceInfo(), e);
            }
        }

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