/*
 * 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 IllegalStateException(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 IllegalStateException(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 IllegalStateException(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 IllegalStateException(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;
    }
}
