/*
 * Copyright 2016-present 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.drivers.juniper;

//import com.google.common.base.Optional;

import com.google.common.annotations.Beta;
import com.google.common.collect.Iterables;
import org.onosproject.drivers.utilities.XmlConfigParser;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Port;
import org.onosproject.net.behaviour.LinkDiscovery;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
import org.onosproject.net.link.LinkDescription;
import org.onosproject.netconf.NetconfController;
import org.onosproject.netconf.NetconfException;
import org.onosproject.netconf.NetconfSession;
import org.slf4j.Logger;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;

import static com.google.common.base.Preconditions.checkNotNull;
import static org.onosproject.drivers.juniper.JuniperUtils.LinkAbstraction;
import static org.onosproject.drivers.juniper.JuniperUtils.parseJuniperLldp;
import static org.onosproject.drivers.juniper.JuniperUtils.requestBuilder;
import static org.onosproject.net.AnnotationKeys.PORT_NAME;
import static org.onosproject.drivers.juniper.JuniperUtils.REQ_LLDP_NBR_INFO;
import static org.onosproject.drivers.juniper.JuniperUtils.FAILED_CFG;
import static org.slf4j.LoggerFactory.getLogger;


/**
 * Retrieve Links discovered by the device LLDP.
 * Tested with MX240 junos 14.2
 */
@Beta
public class LinkDiscoveryJuniperImpl extends AbstractHandlerBehaviour
        implements LinkDiscovery {

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

    @Override
    public Set<LinkDescription> getLinks() {
        DeviceId localDeviceId = this.handler().data().deviceId();
        NetconfController controller =
                checkNotNull(handler().get(NetconfController.class));
        NetconfSession session =
                controller.getDevicesMap().get(localDeviceId).getSession();

        String reply;
        try {
            reply = session.get(requestBuilder(REQ_LLDP_NBR_INFO));
        } catch (IOException e) {
            throw new RuntimeException(new NetconfException(FAILED_CFG, e));
        }
        log.debug("Reply from device {} : {}", localDeviceId, reply);
        Set<LinkAbstraction> linkAbstractions = parseJuniperLldp(
                XmlConfigParser.loadXml(new ByteArrayInputStream(reply.getBytes())));
        log.debug("Set of LinkAbstraction discovered {}", linkAbstractions);

        DeviceService deviceService = this.handler().get(DeviceService.class);
        Set<LinkDescription> descriptions = new HashSet<>();

        //for each lldp neighbor create two LinkDescription
        for (LinkAbstraction linkAbs : linkAbstractions) {

            //find source port by local port name
            Optional<Port> localPort = deviceService.getPorts(localDeviceId).stream()
                    .filter(port -> {
                        if (linkAbs.localPortName.equals(
                                port.annotations().value(PORT_NAME))) {
                            return true;
                        }
                        return false;
                    }).findAny();
            if (!localPort.isPresent()) {
                log.warn("Port name {} does not exist in device {}",
                         linkAbs.localPortName, localDeviceId);
                continue;
            }
            //find destination device by remote chassis id
            com.google.common.base.Optional<Device> dev = Iterables.tryFind(
                    deviceService.getAvailableDevices(),
                    input -> input.chassisId().equals(linkAbs.remoteChassisId));

            if (!dev.isPresent()) {
                log.warn("Device with chassis ID {} does not exist",
                         linkAbs.remoteChassisId);
                continue;
            }
            Device remoteDevice = dev.get();

            //find destination port by interface index
            Optional<Port> remotePort = deviceService.getPorts(remoteDevice.id())
                    .stream().filter(port -> {
                if (port.annotations().value("index") != null &&
                        Integer.parseInt(port.annotations().value("index"))
                                == linkAbs.remotePortIndex) {
                    return true;
                }
                return false;
            }).findAny();
            if (!remotePort.isPresent()) {
                log.warn("Port with index {} does not exist in device {}",
                         linkAbs.remotePortIndex, remoteDevice.id());
                continue;
            }

            JuniperUtils.createBiDirLinkDescription(localDeviceId,
                                                    localPort.get(),
                                               remoteDevice.id(),
                                               remotePort.get(),
                                               descriptions);

        }
        return descriptions;
    }
}
