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

import com.google.common.collect.ImmutableList;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IPv4;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.PIM;
import org.onlab.packet.pim.PIMAddrUnicast;
import org.onlab.packet.pim.PIMHello;
import org.onlab.packet.pim.PIMHelloOption;
import org.onlab.packet.pim.PIMJoinPrune;
import org.onlab.packet.pim.PIMJoinPruneGroup;
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.mcast.McastRoute;
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.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
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 static final int JOIN_PERIOD = 60;
    private static final double HOLD_TIME_MULTIPLIER = 3.5;

    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;

    private final int helloInterval;

    private long lastHello;

    // 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 ConcurrentHashMap<>();

    private Map<McastRoute, RouteData> routes = new ConcurrentHashMap<>();

    /**
     * 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,
                         int helloInterval,
                         short holdTime,
                         int priority,
                         short propagationDelay,
                         short overrideInterval,
                         PacketService packetService) {

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

        lastHello = 0;

        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 List<InterfaceIpAddress> getIpAddresses() {
        return onosInterface.ipAddressesList();
    }

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

        IpAddress ipaddr = null;
        for (InterfaceIpAddress ifipaddr : onosInterface.ipAddressesList()) {
            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 ImmutableList.copyOf(pimNeighbors.values());
    }

    public Collection<McastRoute> getRoutes() {
        return routes.keySet();
    }

    /**
     * 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() {
        if (lastHello + TimeUnit.SECONDS.toMillis(helloInterval) >
                System.currentTimeMillis()) {
            return;
        }

        lastHello = System.currentTimeMillis();

        // 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) {
        if (log.isTraceEnabled()) {
            log.trace("Received a PIM hello packet");
        }

        // 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) {

        IPv4 ip = (IPv4) ethPkt.getPayload();
        checkNotNull(ip);

        PIM pim = (PIM) ip.getPayload();
        checkNotNull(pim);

        PIMJoinPrune jpHdr = (PIMJoinPrune) pim.getPayload();
        checkNotNull(jpHdr);

        /*
         * The Join/Prune messages are grouped by Group address. We'll walk each group address
         * where we will possibly have to walk a list of source address for the joins and prunes.
         */
        Collection<PIMJoinPruneGroup> jpgs = jpHdr.getJoinPrunes();
        for (PIMJoinPruneGroup jpg : jpgs) {
            IpPrefix gpfx = jpg.getGroup();

            // Walk the joins first.
            for (IpPrefix spfx : jpg.getJoins().values()) {

                // We may need


            }

            for (IpPrefix spfx : jpg.getPrunes().values()) {

                // TODO: this is where we many need to remove multi-cast state and possibly intents.

            }
        }

    }

    public void addRoute(McastRoute route, IpAddress nextHop, MacAddress nextHopMac) {
        RouteData data = new RouteData(nextHop, nextHopMac);
        routes.put(route, data);

        sendJoinPrune(route, data, true);
    }

    public void removeRoute(McastRoute route) {
        RouteData data = routes.remove(route);

        if (data != null) {
            sendJoinPrune(route, data, false);
        }
    }

    public void sendJoins() {
        routes.entrySet().forEach(entry -> {
            if (entry.getValue().timestamp + TimeUnit.SECONDS.toMillis(JOIN_PERIOD) >
                    System.currentTimeMillis()) {
                return;
            }

            sendJoinPrune(entry.getKey(), entry.getValue(), true);
        });
    }

    private void sendJoinPrune(McastRoute route, RouteData data, boolean join) {
        PIMJoinPrune jp = new PIMJoinPrune();

        jp.addJoinPrune(route.source().toIpPrefix(), route.group().toIpPrefix(), join);
        jp.setHoldTime(join ? (short) Math.floor(JOIN_PERIOD * HOLD_TIME_MULTIPLIER) : 0);
        jp.setUpstreamAddr(new PIMAddrUnicast(data.ipAddress.toString()));

        PIM pim = new PIM();
        pim.setPIMType(PIM.TYPE_JOIN_PRUNE_REQUEST);
        pim.setPayload(jp);

        IPv4 ipv4 = new IPv4();
        ipv4.setDestinationAddress(PIM.PIM_ADDRESS.getIp4Address().toInt());
        ipv4.setSourceAddress(getIpAddress().getIp4Address().toInt());
        ipv4.setProtocol(IPv4.PROTOCOL_PIM);
        ipv4.setTtl((byte) 1);
        ipv4.setDiffServ((byte) 0xc0);
        ipv4.setPayload(pim);

        Ethernet eth = new Ethernet();
        eth.setSourceMACAddress(onosInterface.mac());
        eth.setDestinationMACAddress(MacAddress.valueOf("01:00:5E:00:00:0d"));
        eth.setEtherType(Ethernet.TYPE_IPV4);
        eth.setPayload(ipv4);

        TrafficTreatment treatment = DefaultTrafficTreatment.builder()
                .setOutput(onosInterface.connectPoint().port())
                .build();

        packetService.emit(new DefaultOutboundPacket(onosInterface.connectPoint().deviceId(),
                treatment, ByteBuffer.wrap(eth.serialize())));

        data.timestamp = System.currentTimeMillis();
    }

    /**
     * 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 int helloInterval = PimInterfaceManager.DEFAULT_HELLO_INTERVAL;
        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;
        }

        /**
         * Users the specified hello interval.
         *
         * @param helloInterval hello interval in seconds
         * @return this PIM interface builder
         */
        public Builder withHelloInterval(int helloInterval) {
            this.helloInterval = helloInterval;
            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, helloInterval, holdtime, priority,
                    propagationDelay, overrideInterval, packetService);
        }

    }

    private static class RouteData {
        public final IpAddress ipAddress;
        public final MacAddress macAddress;
        public long timestamp;

        public RouteData(IpAddress ip, MacAddress mac) {
            this.ipAddress = ip;
            this.macAddress = mac;
            timestamp = System.currentTimeMillis();
        }
    }
}
