/*
 * Copyright 2016 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.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.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 (NetconfException 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 (NetconfException 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 (NetconfException 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 (NetconfException 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;
    }
}
