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

import org.onlab.packet.Ethernet;
import org.onlab.packet.IPv4;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.PIM;
import org.onlab.packet.pim.PIMHello;
import org.onlab.packet.pim.PIMHelloOption;
import org.onosproject.incubator.net.intf.Interface;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.host.InterfaceIpAddress;
import org.onosproject.net.packet.DefaultOutboundPacket;
import org.onosproject.net.packet.PacketService;
import org.slf4j.Logger;

import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.stream.Collectors;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * PIM Interface represents an ONOS Interface with IP and MAC addresses for
 * a given ConnectPoint.
 */
public final class PIMInterface {

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

    private final PacketService packetService;

    private Interface onosInterface;
    private final TrafficTreatment outputTreatment;

    // Our hello opt holdtime
    private short holdtime = PIMHelloOption.DEFAULT_HOLDTIME;

    // Our hello opt prune delay
    private int pruneDelay = PIMHelloOption.DEFAULT_PRUNEDELAY;

    // Neighbor priority
    private int priority   = PIMHelloOption.DEFAULT_PRIORITY;

    // Our current genid
    private final int generationId;

    // The IP address of the DR
    private IpAddress drIpaddress;

    // A map of all our PIM neighbors keyed on our neighbors IP address
    private Map<IpAddress, PIMNeighbor> pimNeighbors = new HashMap<>();

    /**
     * Create a PIMInterface from an ONOS Interface.
     *
     * @param intf the ONOS Interface.
     * @param holdTime hold time
     * @param priority priority
     * @param propagationDelay propagation delay
     * @param overrideInterval override interval
     * @param packetService reference to the packet service
     */
    private PIMInterface(Interface intf,
                        short holdTime,
                        int priority,
                        short propagationDelay,
                        short overrideInterval,
                        PacketService packetService) {

        onosInterface = intf;
        outputTreatment = createOutputTreatment();
        this.holdtime = holdTime;
        this.packetService = packetService;
        IpAddress ourIp = getIpAddress();
        MacAddress mac = intf.mac();

        generationId = new Random().nextInt();

        // Create a PIM Neighbor to represent ourselves for DR election.
        PIMNeighbor us = new PIMNeighbor(ourIp, mac, holdTime, 0, priority, generationId);

        pimNeighbors.put(ourIp, us);
        drIpaddress = ourIp;
    }

    private TrafficTreatment createOutputTreatment() {
        return DefaultTrafficTreatment.builder()
                .setOutput(onosInterface.connectPoint().port())
                .build();
    }

    /**
     * Return the ONOS Interface.
     *
     * @return ONOS Interface.
     */
    public Interface getInterface() {
        return onosInterface;

    }

    /**
     * Set the ONOS Interface, it will override a previous value.
     *
     * @param intf ONOS Interface
     * @return PIM interface instance
     */
    public PIMInterface setInterface(Interface intf) {
        onosInterface = intf;
        return this;
    }

    /**
     * Get the set of IP Addresses associated with this interface.
     *
     * @return a set of Ip Addresses on this interface
     */
    public Set<InterfaceIpAddress> getIpAddresses() {
        return onosInterface.ipAddresses();
    }

    /**
     * Return a single "best" IP address.
     *
     * @return the choosen IP address or null if none
     */
    public IpAddress getIpAddress() {
        if (onosInterface.ipAddresses().isEmpty()) {
            return null;
        }

        IpAddress ipaddr = null;
        for (InterfaceIpAddress ifipaddr : onosInterface.ipAddresses()) {
            ipaddr = ifipaddr.ipAddress();
            break;
        }
        return ipaddr;
    }

    /**
     * Get the holdtime.
     *
     * @return the holdtime
     */
    public short getHoldtime() {
        return holdtime;
    }

    /**
     * Get the prune delay.
     *
     * @return The prune delay
     */
    public int getPruneDelay() {
        return pruneDelay;
    }

    /**
     * Get our hello priority.
     *
     * @return our priority
     */
    public int getPriority() {
        return priority;
    }

    /**
     * Get our generation ID.
     *
     * @return our generation ID
     */
    public int getGenerationId() {
        return generationId;
    }

    /**
     * Gets the neighbors seen on this interface.
     *
     * @return PIM neighbors
     */
    public Collection<PIMNeighbor> getNeighbors() {
        return pimNeighbors.values();
    }

    /**
     * Checks whether any of our neighbors have expired, and cleans up their
     * state if they have.
     */
    public void checkNeighborTimeouts() {
        Set<PIMNeighbor> expired = pimNeighbors.values().stream()
                // Don't time ourselves out!
                .filter(neighbor -> !neighbor.ipAddress().equals(getIpAddress()))
                .filter(neighbor -> neighbor.isExpired())
                .collect(Collectors.toSet());

        for (PIMNeighbor neighbor : expired) {
            log.info("Timing out neighbor {}", neighbor);
            pimNeighbors.remove(neighbor.ipAddress(), neighbor);
        }
    }

    /**
     * Multicast a hello message out our interface.  This hello message is sent
     * periodically during the normal PIM Neighbor refresh time, as well as a
     * result of a newly created interface.
     */
    public void sendHello() {
        // Create the base PIM Packet and mark it a hello packet
        PIMPacket pimPacket = new PIMPacket(PIM.TYPE_HELLO);

        // We need to set the source MAC and IPv4 addresses
        pimPacket.setSrcMacAddr(onosInterface.mac());
        pimPacket.setSrcIpAddress(Ip4Address.valueOf(getIpAddress().toOctets()));

        // Create the hello message with options
        PIMHello hello = new PIMHello();
        hello.createDefaultOptions();
        hello.addOption(PIMHelloOption.createHoldTime(holdtime));
        hello.addOption(PIMHelloOption.createPriority(priority));
        hello.addOption(PIMHelloOption.createGenID(generationId));

        // Now set the hello option payload
        pimPacket.setPIMPayload(hello);

        packetService.emit(new DefaultOutboundPacket(
                onosInterface.connectPoint().deviceId(),
                outputTreatment,
                ByteBuffer.wrap(pimPacket.getEthernet().serialize())));
    }

    /**
     * Process an incoming PIM Hello message.  There are a few things going on in
     * this method:
     * <ul>
     *     <li>We <em>may</em> have to create a new neighbor if one does not already exist</li>
     *     <li>We <em>may</em> need to re-elect a new DR if new information is received</li>
     *     <li>We <em>may</em> need to send an existing neighbor all joins if the genid changed</li>
     *     <li>We will refresh the neighbor's timestamp</li>
     * </ul>
     *
     * @param ethPkt the Ethernet packet header
     */
    public void processHello(Ethernet ethPkt) {

        // We'll need to save our neighbors MAC address
        MacAddress nbrmac = ethPkt.getSourceMAC();

        // And we'll need to save neighbors IP Address.
        IPv4 iphdr = (IPv4) ethPkt.getPayload();
        IpAddress srcip = IpAddress.valueOf(iphdr.getSourceAddress());

        PIM pimhdr = (PIM) iphdr.getPayload();
        if (pimhdr.getPimMsgType() != PIM.TYPE_HELLO) {
            log.error("process Hello has received a non hello packet type: " + pimhdr.getPimMsgType());
            return;
        }

        // get the DR values for later calculation
        PIMNeighbor dr = pimNeighbors.get(drIpaddress);
        checkNotNull(dr);

        IpAddress drip = drIpaddress;
        int drpri = dr.priority();

        // Assume we do not need to run a DR election
        boolean reElectDr = false;
        boolean genidChanged = false;

        PIMHello hello = (PIMHello) pimhdr.getPayload();

        // Determine if we already have a PIMNeighbor
        PIMNeighbor nbr = pimNeighbors.getOrDefault(srcip, null);
        PIMNeighbor newNbr = PIMNeighbor.createPimNeighbor(srcip, nbrmac, hello.getOptions().values());

        if (nbr == null) {
            pimNeighbors.putIfAbsent(srcip, newNbr);
            nbr = newNbr;
        } else if (!nbr.equals(newNbr)) {
            if (newNbr.holdtime() == 0) {
                // Neighbor has shut down. Remove them and clean up
                pimNeighbors.remove(srcip, nbr);
                return;
            } else {
                // Neighbor has changed one of their options.
                pimNeighbors.put(srcip, newNbr);
                nbr = newNbr;
            }
        }

        // Refresh this neighbor's timestamp
        nbr.refreshTimestamp();

        /*
         * the election method will first determine if an election
         * needs to be run, if so it will run the election.  The
         * IP address of the DR will be returned.  If the IP address
         * of the DR is different from what we already have we know a
         * new DR has been elected.
         */
        IpAddress electedIp = election(nbr, drip, drpri);
        if (!drip.equals(electedIp)) {
            // we have a new DR.
            drIpaddress = electedIp;
        }
    }

    // Run an election if we need to.  Return the elected IP address.
    private IpAddress election(PIMNeighbor nbr, IpAddress drIp, int drPriority) {

        IpAddress nbrIp = nbr.ipAddress();
        if (nbr.priority() > drPriority) {
            return nbrIp;
        }

        if (nbrIp.compareTo(drIp) > 0) {
            return nbrIp;
        }
        return drIp;
    }

    /**
     * Process an incoming PIM JoinPrune message.
     *
     * @param ethPkt the Ethernet packet header.
     */
    public void processJoinPrune(Ethernet ethPkt) {
        // TODO: add Join/Prune processing code.
    }

    /**
     * Returns a builder for a PIM interface.
     *
     * @return PIM interface builder
     */
    public static Builder builder() {
        return new Builder();
    }

    /**
     * Builder for a PIM interface.
     */
    public static class Builder {
        private Interface intf;
        private PacketService packetService;
        private short holdtime = PIMHelloOption.DEFAULT_HOLDTIME;
        private int priority   = PIMHelloOption.DEFAULT_PRIORITY;
        private short propagationDelay = PIMHelloOption.DEFAULT_PRUNEDELAY;
        private short overrideInterval = PIMHelloOption.DEFAULT_OVERRIDEINTERVAL;

        /**
         * Uses the specified ONOS interface.
         *
         * @param intf ONOS interface
         * @return this PIM interface builder
         */
        public Builder withInterface(Interface intf) {
            this.intf = checkNotNull(intf);
            return this;
        }

        /**
         * Sets the reference to the packet service.
         *
         * @param packetService packet service
         * @return this PIM interface builder
         */
        public Builder withPacketService(PacketService packetService) {
            this.packetService = checkNotNull(packetService);
            return this;
        }

        /**
         * Uses the specified hold time.
         *
         * @param holdTime hold time in seconds
         * @return this PIM interface builder
         */
        public Builder withHoldTime(short holdTime) {
            this.holdtime = holdTime;
            return this;
        }

        /**
         * Uses the specified DR priority.
         *
         * @param priority DR priority
         * @return this PIM interface builder
         */
        public Builder withPriority(int priority) {
            this.priority = priority;
            return this;
        }

        /**
         * Uses the specified propagation delay.
         *
         * @param propagationDelay propagation delay in ms
         * @return this PIM interface builder
         */
        public Builder withPropagationDelay(short propagationDelay) {
            this.propagationDelay = propagationDelay;
            return this;
        }

        /**
         * Uses the specified override interval.
         *
         * @param overrideInterval override interval in ms
         * @return this PIM interface builder
         */
        public Builder withOverrideInterval(short overrideInterval) {
            this.overrideInterval = overrideInterval;
            return this;
        }

        /**
         * Builds the PIM interface.
         *
         * @return PIM interface
         */
        public PIMInterface build() {
            checkArgument(intf != null, "Must provide an interface");
            checkArgument(packetService != null, "Must provide a packet service");

            return new PIMInterface(intf, holdtime, priority, propagationDelay,
                    overrideInterval, packetService);
        }

    }
}
