/*
 * Copyright 2016 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.annotations.Beta;
import com.google.common.base.Strings;
import org.apache.commons.lang.StringUtils;
import org.onlab.packet.Ip4Address;
import org.onosproject.net.AnnotationKeys;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.FlowRuleProgrammable;
import org.onosproject.net.flow.FlowRuleService;
import org.onosproject.net.flow.criteria.Criterion;
import org.onosproject.net.flow.criteria.IPCriterion;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
import org.onosproject.net.link.LinkService;
import org.onosproject.netconf.DatastoreId;
import org.onosproject.netconf.NetconfController;
import org.onosproject.netconf.NetconfException;
import org.onosproject.netconf.NetconfSession;

import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import static com.google.common.base.Preconditions.checkNotNull;
import static org.onosproject.drivers.juniper.JuniperUtils.OperationType;
import static org.onosproject.drivers.juniper.JuniperUtils.OperationType.ADD;
import static org.onosproject.drivers.juniper.JuniperUtils.OperationType.REMOVE;
import static org.onosproject.drivers.juniper.JuniperUtils.commitBuilder;
import static org.onosproject.drivers.juniper.JuniperUtils.rollbackBuilder;
import static org.onosproject.drivers.juniper.JuniperUtils.routeAddBuilder;
import static org.onosproject.drivers.juniper.JuniperUtils.routeDeleteBuilder;
import static org.onosproject.drivers.utilities.XmlConfigParser.loadXmlString;
import static org.onosproject.net.flow.FlowEntry.FlowEntryState.PENDING_REMOVE;
import static org.onosproject.net.flow.FlowEntry.FlowEntryState.REMOVED;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Conversion of FlowRules into static routes and retrieve of installed
 * static routes as FlowRules.
 * The selector of the FlowRule must contains the IPv4 address
 * {@link org.onosproject.net.flow.TrafficSelector.Builder#matchIPDst(org.onlab.packet.IpPrefix)}
 * of the host to connect and the treatment must include an
 * output port {@link org.onosproject.net.flow.TrafficTreatment.Builder#setOutput(PortNumber)}
 * All other instructions in the selector and treatment are ignored.
 * <p>
 * This implementation requires an IP adjacency
 * (e.g., IP link discovered by {@link LinkDiscoveryJuniperImpl}) between the routers
 * to find the next hop IP address.
 */
@Beta
public class FlowRuleJuniperImpl extends AbstractHandlerBehaviour
        implements FlowRuleProgrammable {

    private static final String OK = "<ok/>";
    public static final String IP_STRING = "ip";
    private final org.slf4j.Logger log = getLogger(getClass());

    @Override
    public Collection<FlowEntry> getFlowEntries() {

        DeviceId devId = checkNotNull(this.data().deviceId());
        NetconfController controller = checkNotNull(handler().get(NetconfController.class));
        NetconfSession session = controller.getDevicesMap().get(devId).getSession();
        if (session == null) {
            log.warn("Device {} is not registered in netconf", devId);
            return Collections.EMPTY_LIST;
        }

        //Installed static routes
        String reply;
        try {
            reply = session.get(routingTableBuilder());
        } catch (IOException e) {
            throw new RuntimeException(new NetconfException("Failed to retrieve configuration.",
                    e));
        }
        Collection<StaticRoute> devicesStaticRoutes =
                JuniperUtils.parseRoutingTable(loadXmlString(reply));

        //Expected FlowEntries installed
        FlowRuleService flowRuleService = this.handler().get(FlowRuleService.class);
        Iterable<FlowEntry> flowEntries = flowRuleService.getFlowEntries(devId);

        Collection<FlowEntry> installedRules = new HashSet<>();
        flowEntries.forEach(flowEntry -> {
            Optional<IPCriterion> ipCriterion = getIpCriterion(flowEntry);
            if (!ipCriterion.isPresent()) {
                return;
            }

            Optional<OutputInstruction> output = getOutput(flowEntry);
            if (!output.isPresent()) {
                return;
            }
            //convert FlowRule into static route
            getStaticRoute(devId, ipCriterion.get(), output.get(), flowEntry.priority()).ifPresent(staticRoute -> {
                //Two type of FlowRules:
                //1. FlowRules to forward to a remote subnet: they are translated into static route
                // configuration. So a removal request will be processed.
                //2. FlowRules to forward on a subnet directly attached to the router (Generally speaking called local):
                // those routes do not require any configuration because the router is already able to forward on
                // directly attached subnet. In this case, when the driver receive the request to remove,
                // it will report as removed.

                if (staticRoute.isLocalRoute()) {
                    //if the FlowRule is in PENDING_REMOVE or REMOVED, it is not reported.
                    if (flowEntry.state() == PENDING_REMOVE || flowEntry.state() == REMOVED) {
                        devicesStaticRoutes.remove(staticRoute);
                    } else {
                        //FlowRule is reported installed
                        installedRules.add(flowEntry);
                        devicesStaticRoutes.remove(staticRoute);
                    }

                } else {
                    //if the route is found in the device, the FlowRule is reported installed.
                    if (devicesStaticRoutes.contains(staticRoute)) {
                        installedRules.add(flowEntry);
                        devicesStaticRoutes.remove(staticRoute);
                    }
                }
            });
        });

        if (!devicesStaticRoutes.isEmpty()) {
            log.info("Found static routes on device {} not installed by ONOS: {}",
                    devId, devicesStaticRoutes);
//            FIXME: enable configuration to purge already installed flows.
//            It cannot be allowed by default because it may remove needed management routes
//            log.warn("Removing from device {} the FlowEntries not expected {}", deviceId, devicesStaticRoutes);
//            devicesStaticRoutes.forEach(staticRoute -> editRoute(session, REMOVE, staticRoute));
        }
        return installedRules;
    }

    @Override
    public Collection<FlowRule> applyFlowRules(Collection<FlowRule> rules) {
        return manageRules(rules, ADD);
    }

    @Override
    public Collection<FlowRule> removeFlowRules(Collection<FlowRule> rules) {
        return manageRules(rules, REMOVE);
    }

    private Collection<FlowRule> manageRules(Collection<FlowRule> rules, OperationType type) {

        DeviceId deviceId = this.data().deviceId();

        log.debug("{} flow entries to NETCONF device {}", type, deviceId);
        NetconfController controller = checkNotNull(handler()
                .get(NetconfController.class));
        NetconfSession session = controller.getDevicesMap().get(deviceId)
                .getSession();
        Collection<FlowRule> managedRules = new HashSet<>();

        for (FlowRule flowRule : rules) {

            Optional<IPCriterion> ipCriterion = getIpCriterion(flowRule);
            if (!ipCriterion.isPresent()) {
                log.error("Currently not supported: IPv4 destination match must be used");
                continue;
            }

            Optional<OutputInstruction> output = getOutput(flowRule);
            if (!output.isPresent()) {
                log.error("Currently not supported: the output action is needed");
                continue;
            }

            getStaticRoute(deviceId, ipCriterion.get(), output.get(), flowRule.priority()).ifPresent(
                    staticRoute -> {
                        //If the static route is not local, the driver tries to install
                        if (!staticRoute.isLocalRoute()) {
                            //Only if the installation is successful, the driver report the
                            // FlowRule as installed.
                            if (editRoute(session, type, staticRoute)) {
                                managedRules.add(flowRule);
                            }
                            //If static route are local, they are not installed
                            // because are not required. Directly connected routes
                            //are automatically forwarded.
                        } else {
                            managedRules.add(flowRule);
                        }
                    }
            );
        }
        return rules;
    }

    private boolean editRoute(NetconfSession session, OperationType type,
                              StaticRoute staticRoute) {
        try {
            boolean reply = false;
            if (type == ADD) {
                reply = session
                        .editConfig(DatastoreId.CANDIDATE, "merge",
                                routeAddBuilder(staticRoute));
            } else if (type == REMOVE) {
                reply = session
                        .editConfig(DatastoreId.CANDIDATE, "none", routeDeleteBuilder(staticRoute));
            }
            if (reply && commit()) {
                return true;
            } else {
                if (!rollback()) {
                    log.error("Something went wrong in the configuration and impossible to rollback");
                } else {
                    log.error("Something went wrong in the configuration: a static route has not been {} {}",
                            type == ADD ? "added" : "removed", staticRoute);
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(new NetconfException("Failed to retrieve configuration.",
                    e));
        }
        return false;
    }

    /**
     * Helper method to convert FlowRule into an abstraction of static route
     * {@link StaticRoute}.
     *
     * @param devId    the device id
     * @param criteria the IP destination criteria
     * @param output   the output instruction
     * @return optional of Static Route
     */
    private Optional<StaticRoute> getStaticRoute(DeviceId devId,
                                                 IPCriterion criteria,
                                                 OutputInstruction output,
                                                 int priority) {

        DeviceService deviceService = this.handler().get(DeviceService.class);
        Collection<Port> ports = deviceService.getPorts(devId);
        Optional<Port> port = ports.stream().filter(x -> x.number().equals(output.port())).findAny();
        if (!port.isPresent()) {
            log.error("The port {} does not exist in the device",
                    output.port());
            return Optional.empty();
        }

        //Find if the route refers to a local interface.
        Optional<Port> local = deviceService.getPorts(devId).stream().filter(this::isIp)
                .filter(p -> criteria.ip().getIp4Prefix().contains(
                        Ip4Address.valueOf(p.annotations().value(IP_STRING)))).findAny();

        if (local.isPresent()) {
            return Optional.of(new StaticRoute(criteria.ip().getIp4Prefix(),
                    criteria.ip().getIp4Prefix().address(), true, priority));
        }

        Optional<Ip4Address> nextHop = findIpDst(devId, port.get());
        if (nextHop.isPresent()) {
            return Optional.of(
                    new StaticRoute(criteria.ip().getIp4Prefix(), nextHop.get(), false, priority));
        } else {
            log.error("The destination interface has not an IP {}", port.get());
            return Optional.empty();
        }

    }

    /**
     * Helper method to get the IP destination criterion given a flow rule.
     *
     * @param flowRule the flow rule
     * @return optional of IP destination criterion
     */
    private Optional<IPCriterion> getIpCriterion(FlowRule flowRule) {

        Criterion ip = flowRule.selector().getCriterion(Criterion.Type.IPV4_DST);
        return Optional.ofNullable((IPCriterion) ip);
    }

    /**
     * Helper method to get the output instruction given a flow rule.
     *
     * @param flowRule the flow rule
     * @return the output instruction
     */
    private Optional<OutputInstruction> getOutput(FlowRule flowRule) {
        Optional<OutputInstruction> output = flowRule
                .treatment().allInstructions().stream()
                .filter(instruction -> instruction
                        .type() == Instruction.Type.OUTPUT)
                .map(x -> (OutputInstruction) x).findFirst();
        return output;
    }

    private String routingTableBuilder() {
        StringBuilder rpc = new StringBuilder("<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">");
        rpc.append("<get-route-information/>");
        rpc.append("</rpc>");
        return rpc.toString();
    }

    private boolean commit() {
        NetconfController controller = checkNotNull(handler()
                .get(NetconfController.class));
        NetconfSession session = controller.getDevicesMap()
                .get(handler().data().deviceId()).getSession();

        String replay;
        try {
            replay = session.get(commitBuilder());
        } catch (IOException e) {
            throw new RuntimeException(new NetconfException("Failed to retrieve configuration.",
                    e));
        }

        if (replay != null && replay.indexOf(OK) >= 0) {
            return true;
        }
        return false;
    }

    private boolean rollback() {
        NetconfController controller = checkNotNull(handler()
                .get(NetconfController.class));
        NetconfSession session = controller.getDevicesMap()
                .get(handler().data().deviceId()).getSession();

        String replay;
        try {
            replay = session.get(rollbackBuilder(0));
        } catch (IOException e) {
            throw new RuntimeException(new NetconfException("Failed to retrieve configuration.",
                    e));
        }

        if (replay != null && replay.indexOf(OK) >= 0) {
            return true;
        }
        return false;
    }

    /**
     * Helper method to find the next hop IP address.
     * The logic is to check if the destination ports have an IP address
     * by checking the logical interface (e.g., for port physical ge-2/0/1,
     * a logical interface may be ge-2/0/1.0
     *
     * @param deviceId the device id of the flow rule to be installed
     * @param port     output port of the flow rule treatment
     * @return optional IPv4 address of a next hop
     */
    private Optional<Ip4Address> findIpDst(DeviceId deviceId, Port port) {
        LinkService linkService = this.handler().get(LinkService.class);
        Set<Link> links = linkService.getEgressLinks(new ConnectPoint(deviceId, port.number()));
        DeviceService deviceService = this.handler().get(DeviceService.class);
        //Using only links with adjacency discovered by the LLDP protocol (see LinkDiscoveryJuniperImpl)
        Map<DeviceId, Port> dstPorts = links.stream().filter(l ->
                IP_STRING.toUpperCase().equals(l.annotations().value("layer")))
                .collect(Collectors.toMap(
                        l -> l.dst().deviceId(),
                        l -> deviceService.getPort(l.dst().deviceId(), l.dst().port())));
        for (Map.Entry<DeviceId, Port> entry : dstPorts.entrySet()) {
            String portName = entry.getValue().annotations().value(AnnotationKeys.PORT_NAME);

            Optional<Port> childPort = deviceService.getPorts(entry.getKey()).stream()
                    .filter(p -> Strings.nullToEmpty(
                            p.annotations().value(AnnotationKeys.PORT_NAME)).contains(portName.trim()))
                    .filter(p -> isIp(p))
                    .findAny();
            if (childPort.isPresent()) {
                return Optional.ofNullable(Ip4Address.valueOf(childPort.get().annotations().value("ip")));
            }
        }

        return Optional.empty();
    }

    /**
     * Helper method to find if an interface has an IP address.
     * It will check the annotations of the port.
     *
     * @param port the port
     * @return true if the IP address is present. Otherwise false.
     */
    private boolean isIp(Port port) {
        String ip4 = port.annotations().value(IP_STRING);
        if (StringUtils.isEmpty(ip4)) {
            return false;
        }
        try {

            Ip4Address.valueOf(port.annotations().value(IP_STRING));
        } catch (IllegalArgumentException e) {
            return false;
        }
        return true;
    }
}
