/*
 * 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.segmentrouting;

import org.onlab.packet.Ethernet;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;

import org.onlab.packet.MplsLabel;
import org.onosproject.grouphandler.NeighborSet;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultFlowRule;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.group.DefaultGroupKey;
import org.onosproject.net.group.Group;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;

import static com.google.common.base.Preconditions.checkNotNull;

public class RoutingRulePopulator {

    private static final Logger log = LoggerFactory.getLogger(RoutingRulePopulator.class);

    private SegmentRoutingManager srManager;
    private NetworkConfigHandler config;

    /**
     * Creates a RoutingRulePopulator object.
     *
     * @param srManager
     */
    public RoutingRulePopulator(SegmentRoutingManager srManager) {
        this.srManager = srManager;
        this.config = checkNotNull(srManager.networkConfigHandler);
    }

    /**
     * Populates IP flow rules for specific hosts directly connected to the switch.
     *
     * @param deviceId switch ID to set the rules
     * @param hostIp host IP address
     * @param hostMac host MAC address
     * @param outPort port where the host is connected
     */
    public void populateIpRuleForHost(DeviceId deviceId, Ip4Address hostIp,
                                      MacAddress hostMac, PortNumber outPort) {
        TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
        TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();

        sbuilder.matchIPDst(IpPrefix.valueOf(hostIp, 32));
        sbuilder.matchEthType(Ethernet.TYPE_IPV4);

        tbuilder.setEthDst(hostMac)
                .setEthSrc(config.getRouterMacAddress(deviceId))
                .setOutput(outPort);

        TrafficTreatment treatment = tbuilder.build();
        TrafficSelector selector = sbuilder.build();

        FlowRule f = new DefaultFlowRule(deviceId, selector, treatment, 100,
                srManager.appId, 600, false, FlowRule.Type.IP);

        srManager.flowRuleService.applyFlowRules(f);
        log.debug("Flow rule {} is set to switch {}", f, deviceId);
    }

    /**
     * Populates IP flow rules for the subnets of the destination router.
     *
     * @param deviceId switch ID to set the rules
     * @param subnetInfo subnet information
     * @param destSw destination switch ID
     * @param nextHops next hop switch ID list
     * @return true if all rules are set successfully, false otherwise
     */
    public boolean populateIpRuleForSubnet(DeviceId deviceId, String subnetInfo,
                                           DeviceId destSw, Set<DeviceId> nextHops) {

        List<IpPrefix> subnets = extractSubnet(subnetInfo);
        for (IpPrefix subnet: subnets) {
            if (!populateIpRuleForRouter(deviceId, subnet, destSw, nextHops)) {
                return false;
            }
        }

        return true;
    }

    /**
     * Populates IP flow rules for the router IP address.
     *
     * @param deviceId device ID to set the rules
     * @param ipPrefix the IP address of the destination router
     * @param destSw device ID of the destination router
     * @param nextHops next hop switch ID list
     * @return true if all rules are set successfully, false otherwise
     */
    public boolean populateIpRuleForRouter(DeviceId deviceId, IpPrefix ipPrefix,
                                           DeviceId destSw, Set<DeviceId> nextHops) {

        TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
        TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();

        sbuilder.matchIPDst(ipPrefix);
        sbuilder.matchEthType(Ethernet.TYPE_IPV4);

        NeighborSet ns = null;

        //If the next hop is the same as the final destination, then MPLS label is not set.
        if (nextHops.size() == 1 && nextHops.toArray()[0].equals(destSw)) {
            tbuilder.decNwTtl();
            ns = new NeighborSet(nextHops);
        } else {
            tbuilder.copyTtlOut();
            ns = new NeighborSet(nextHops, config.getMplsId(destSw));
        }

        DefaultGroupKey groupKey = (DefaultGroupKey) srManager.getGroupKey(ns);
        if (groupKey == null) {
            log.warn("Group key is not found for ns {}", ns);
            return false;
        }
        Group group = srManager.groupService.getGroup(deviceId, groupKey);
        if (group != null) {
            tbuilder.group(group.id());
        } else {
            log.warn("No group found for NeighborSet {} from {} to {}",
                    ns, deviceId, destSw);
            return false;
        }

        TrafficTreatment treatment = tbuilder.build();
        TrafficSelector selector = sbuilder.build();

        FlowRule f = new DefaultFlowRule(deviceId, selector, treatment, 100,
                srManager.appId, 600, false, FlowRule.Type.IP);

        srManager.flowRuleService.applyFlowRules(f);
        log.debug("IP flow rule {} is set to switch {}", f, deviceId);

        return true;
    }


    /**
     * Populates MPLS flow rules to all transit routers.
     *
     * @param deviceId device ID of the switch to set the rules
     * @param destSwId destination switch device ID
     * @param nextHops next hops switch ID list
     * @return true if all rules are set successfully, false otherwise
     */
    public boolean populateMplsRule(DeviceId deviceId, DeviceId destSwId, Set<DeviceId> nextHops) {

        TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
        Collection<TrafficTreatment> treatments = new ArrayList<>();

        // TODO Handle the case of Bos == false
        sbuilder.matchMplsLabel(MplsLabel.mplsLabel(config.getMplsId(destSwId)));
        sbuilder.matchEthType(Ethernet.MPLS_UNICAST);

        //If the next hop is the destination router, do PHP
        if (nextHops.size() == 1 && destSwId.equals(nextHops.toArray()[0])) {
            TrafficTreatment treatmentBos =
                    getMplsTreatment(deviceId, destSwId, nextHops, true, true);
            TrafficTreatment treatment =
                    getMplsTreatment(deviceId, destSwId, nextHops, true, false);
            if (treatmentBos != null) {
                treatments.add(treatmentBos);
            } else {
                log.warn("Failed to set MPLS rules.");
                return false;
            }
        } else {
            TrafficTreatment treatmentBos =
                    getMplsTreatment(deviceId, destSwId, nextHops, false, true);
            TrafficTreatment treatment =
                    getMplsTreatment(deviceId, destSwId, nextHops, false, false);

            if (treatmentBos != null) {
                treatments.add(treatmentBos);
            } else {
                log.warn("Failed to set MPLS rules.");
                return false;
            }
        }

        TrafficSelector selector = sbuilder.build();
        for (TrafficTreatment treatment: treatments) {
            FlowRule f = new DefaultFlowRule(deviceId, selector, treatment, 100,
                    srManager.appId, 600, false, FlowRule.Type.MPLS);
            srManager.flowRuleService.applyFlowRules(f);
            log.debug("MPLS rule {} is set to {}", f, deviceId);
        }

        return true;
    }


    private TrafficTreatment getMplsTreatment(DeviceId deviceId, DeviceId destSw,
                                             Set<DeviceId> nextHops,
                                             boolean phpRequired, boolean isBos) {

        TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();

        if (phpRequired) {
            tbuilder.copyTtlIn();
            if (isBos) {
                tbuilder.popMpls(Ethernet.TYPE_IPV4)
                        .decNwTtl();
            } else {
                tbuilder.popMpls(Ethernet.MPLS_UNICAST)
                .decMplsTtl();
            }
        } else {
            tbuilder.decMplsTtl();
        }

        if (config.isEcmpNotSupportedInTransit(deviceId)
                && config.isTransitRouter(deviceId)) {
            Link link = selectOneLink(deviceId, nextHops);
            if (link == null) {
                log.warn("No link from {} to {}", deviceId, nextHops);
                return null;
            }
            tbuilder.setEthSrc(config.getRouterMacAddress(deviceId))
                    .setEthDst(config.getRouterMacAddress(link.dst().deviceId()))
                    .setOutput(link.src().port());
        } else {
            NeighborSet ns = new NeighborSet(nextHops);
            DefaultGroupKey groupKey = (DefaultGroupKey) srManager.getGroupKey(ns);
            if (groupKey == null) {
                log.warn("Group key is not found for ns {}", ns);
                return null;
            }
            Group group = srManager.groupService.getGroup(deviceId, groupKey);
            if (group != null) {
                tbuilder.group(group.id());
            } else {
                log.warn("No group found for ns {} key {} in {}", ns,
                        srManager.getGroupKey(ns), deviceId);
                return null;
            }
        }

        return tbuilder.build();
    }

    /**
     * Populates VLAN flows rules.
     * All packets are forwarded to TMAC table.
     *
     * @param deviceId switch ID to set the rules
     */
    public void populateTableVlan(DeviceId deviceId) {
        TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
        TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();

        tbuilder.transition(FlowRule.Type.ETHER);

        TrafficTreatment treatment = tbuilder.build();
        TrafficSelector selector = sbuilder.build();

        FlowRule f = new DefaultFlowRule(deviceId, selector, treatment, 100,
                srManager.appId, 600, false, FlowRule.Type.VLAN);

        srManager.flowRuleService.applyFlowRules(f);

        log.debug("Vlan flow rule {} is set to switch {}", f, deviceId);
    }

    /**
     * Populates TMAC table rules.
     * IP packets are forwarded to IP table.
     * MPLS packets are forwarded to MPLS table.
     *
     * @param deviceId switch ID to set the rules
     */
    public void populateTableTMac(DeviceId deviceId) {

        // flow rule for IP packets
        TrafficSelector selectorIp = DefaultTrafficSelector.builder()
                .matchEthType(Ethernet.TYPE_IPV4)
                .matchEthDst(config.getRouterMacAddress(deviceId))
                .build();
        TrafficTreatment treatmentIp = DefaultTrafficTreatment.builder()
                .transition(FlowRule.Type.IP)
                .build();

        FlowRule flowIp = new DefaultFlowRule(deviceId, selectorIp, treatmentIp, 100,
                srManager.appId, 600, false, FlowRule.Type.ETHER);

        srManager.flowRuleService.applyFlowRules(flowIp);

        // flow rule for MPLS packets
        TrafficSelector selectorMpls = DefaultTrafficSelector.builder()
                .matchEthType(Ethernet.MPLS_UNICAST)
                .matchEthDst(config.getRouterMacAddress(deviceId))
                .build();
        TrafficTreatment treatmentMpls = DefaultTrafficTreatment.builder()
                .transition(FlowRule.Type.MPLS)
                .build();

        FlowRule flowMpls = new DefaultFlowRule(deviceId, selectorMpls, treatmentMpls, 100,
                srManager.appId, 600, false, FlowRule.Type.ETHER);

        srManager.flowRuleService.applyFlowRules(flowMpls);

    }

    /**
     * Populates a table miss entry.
     *
     * @param deviceId switch ID to set rules
     * @param tableToAdd table to set the rules
     * @param toControllerNow flag to send packets to controller immediately
     * @param toControllerWrite flag to send packets to controller at the end of pipeline
     * @param toTable flag to send packets to a specific table
     * @param tableToSend table type to send packets when the toTable flag is set
     */
    public void populateTableMissEntry(DeviceId deviceId, FlowRule.Type tableToAdd, boolean toControllerNow,
                                       boolean toControllerWrite,
                                       boolean toTable, FlowRule.Type tableToSend) {
        // TODO: Change arguments to EnumSet
        TrafficSelector selector = DefaultTrafficSelector.builder()
                .build();
        TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();

        if (toControllerNow) {
            tBuilder.setOutput(PortNumber.CONTROLLER);
        }

        if (toControllerWrite) {
            tBuilder.deferred().setOutput(PortNumber.CONTROLLER);
        }

        if (toTable) {
            tBuilder.transition(tableToSend);
        }

        FlowRule flow = new DefaultFlowRule(deviceId, selector, tBuilder.build(), 0,
                srManager.appId, 600, false, tableToAdd);

        srManager.flowRuleService.applyFlowRules(flow);

    }


    private List<IpPrefix> extractSubnet(String subnetInfo) {
        List<IpPrefix> subnetIpPrefixes = new ArrayList<>();

        // TODO: refactoring required depending on the format of the subnet info
        IpPrefix prefix = IpPrefix.valueOf(subnetInfo);
        if (prefix == null) {
            log.error("Wrong ip prefix type {}", subnetInfo);
        } else {
            subnetIpPrefixes.add(prefix);
        }

        return subnetIpPrefixes;
    }

    private Link selectOneLink(DeviceId srcId, Set<DeviceId> destIds) {

        Set<Link> links = srManager.linkService.getDeviceEgressLinks(srcId);
        DeviceId destId = (DeviceId) destIds.toArray()[0];
        for (Link link: links) {
            if (link.dst().deviceId().equals(destId)) {
                return link;
            }
        }

        return null;
    }

}
