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

import org.onlab.packet.BasePacket;
import org.onlab.packet.Deserializer;
import org.onlab.packet.IPacket;
import org.onlab.packet.IpPrefix;

import java.nio.ByteBuffer;
import java.util.HashMap;

import static com.google.common.base.MoreObjects.toStringHelper;
import static org.onlab.packet.PacketUtils.checkInput;

public class PIMJoinPrune extends BasePacket {

    private PIMAddrUnicast upstreamAddr = new PIMAddrUnicast();
    private short holdTime = (short) 0xffff;

    private class JoinPruneGroup {
        protected IpPrefix group;
        protected HashMap<IpPrefix, IpPrefix> joins = new HashMap<>();
        protected HashMap<IpPrefix, IpPrefix> prunes = new HashMap<>();

        public JoinPruneGroup(IpPrefix grp) {
            group = grp;
        }
    }
    private HashMap<IpPrefix, JoinPruneGroup> joinPrunes = new HashMap<>();

    /**
     * Get the J/P hold time.
     *
     * @return specified in seconds.
     */
    public short getHoldTime() {
        return holdTime;
    }

    /**
     * Set the J/P holdtime in seconds.
     *
     * @param holdTime return the holdtime.
     */
    public void setHoldTime(short holdTime) {
        this.holdTime = holdTime;
    }

    /**
     * Get the upstreamAddr for this J/P request.
     *
     * @return the upstream address.
     */
    public PIMAddrUnicast getUpstreamAddr() {
        return upstreamAddr;
    }

    /**
     * Set the upstream address of this PIM J/P request.
     *
     * @param upstr the PIM Upstream unicast address
     */
    public void setUpstreamAddr(PIMAddrUnicast upstr) {
        this.upstreamAddr = upstr;
    }

    /**
     * Add the specified s,g to join field.
     *
     * @param saddr the source address of the route
     * @param gaddr the group address of the route
     * @param join true for a join, false for a prune.
     */
    public void addJoinPrune(String saddr, String gaddr, boolean join) {
        IpPrefix gpfx = IpPrefix.valueOf(gaddr);
        IpPrefix spfx = IpPrefix.valueOf(saddr);
        addJoinPrune(spfx, gpfx, join);
    }

    /**
     * Add the specified S, G to the join field.
     *
     * @param spfx the source prefix of the route
     * @param gpfx the group prefix of the route
     * @param join true for join, false for prune
     */
    public void addJoinPrune(IpPrefix spfx, IpPrefix gpfx, boolean join) {
        JoinPruneGroup jpg = joinPrunes.get(gpfx);
        if (jpg == null) {
            jpg = new JoinPruneGroup(gpfx);
            joinPrunes.put(gpfx, jpg);
        }

        HashMap<IpPrefix, IpPrefix> members = (join) ? jpg.joins : jpg.prunes;
        if (members.get(spfx) == null) {
            members.put(spfx, spfx);
        }
    }

    /**
     * Add a join given strings represending the source and group addresses.
     *
     * @param saddr source address
     * @param gaddr group address
     */
    public void addJoin(String saddr, String gaddr) {
        this.addJoinPrune(saddr, gaddr, true);
    }

    /**
     * Add a prune given strings represending the source and group addresses.
     *
     * @param saddr source address
     * @param gaddr group address
     */
    public void addPrune(String saddr, String gaddr) {
        this.addJoinPrune(saddr, gaddr, false);
    }

    /**
     * Sets all payloads parent packet if applicable, then serializes this
     * packet and all payloads.
     *
     * @return a byte[] containing this packet and payloads
     */
    @Override
    public byte[] serialize() {

        byte[] data = new byte[8096];      // Come up with something better
        ByteBuffer bb = ByteBuffer.wrap(data);

        bb.put(upstreamAddr.serialize());
        bb.put((byte) 0);    // reserved

        int ngrps = joinPrunes.size();
        bb.put((byte) ngrps);
        bb.putShort(this.holdTime);

        // Walk the group list and input all groups
        for (JoinPruneGroup jpg : joinPrunes.values()) {
            PIMAddrGroup grp = new PIMAddrGroup(jpg.group);
            bb.put(grp.serialize());

            // put the number of joins and prunes
            bb.putShort((short) jpg.joins.size());
            bb.putShort((short) jpg.prunes.size());

            // Set all of the joins
            for (IpPrefix spfx : jpg.joins.values()) {
                PIMAddrSource src = new PIMAddrSource(spfx);
                bb.put(src.serialize());
            }

            // Set all of the prunes
            for (IpPrefix spfx : jpg.prunes.values()) {
                PIMAddrSource src = new PIMAddrSource(spfx);
                bb.put(src.serialize());
            }
        }

        int len = bb.position();
        byte[] data2 = new byte[len];
        bb = ByteBuffer.wrap(data2, 0, len);
        bb.put(data, 0, len);
        return data2;
    }

    // TODO: I suppose I really need to implement this?
    @Override
    public IPacket deserialize(final byte[] data, final int offset,
                               final int length) {
        final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
        return this;
    }

    /**
     * Return the J/P deserializer function.
     *
     * @return a function that will deserialize a J/P message.
     */
    public static Deserializer<PIMJoinPrune> deserializer() {
        return (data, offset, length) -> {

            /*
             * Delay buffer checks until we read enough of the packet to know how
             * much data we will require.  Each encoded address deserializer function
             * will ensure there is enough data for that address.
             */
            PIMJoinPrune jp = new PIMJoinPrune();
            final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);

            // We must get a PIM encoded unicast address
            PIMAddrUnicast upstream = new PIMAddrUnicast();
            upstream.deserialize(bb);
            jp.setUpstreamAddr(upstream);

            // Use this boolean to determine the buffer space we need according to address sizes
            boolean ipv4 = upstream.getAddr().isIp4();

            // We need at minimum 4 bytes for reserved(1), ngroups(1) & holdtime(2)
            checkInput(bb.array(), bb.position(), bb.limit() - bb.position(), 4);

            // get and skip the reserved byte
            bb.get();

            // Get the number of groups.
            int ngroups = bb.get();

            // Save the holdtime.
            jp.setHoldTime(bb.getShort());


            for (int i = 0; i < ngroups; i++) {
                PIMAddrGroup grp = new PIMAddrGroup();

                /*
                 * grp.deserialize will ensure the buffer has enough data to read the group address.
                 */
                grp.deserialize(bb);

                checkInput(bb.array(), bb.position(), bb.limit() - bb.position(), 4);
                int njoins = bb.getShort();
                int nprunes = bb.getShort();

                /*
                 * Now we'll verify we have enough buffer to read the next
                 * group of join and prune addresses for this group.
                 */
                int required = (njoins + nprunes) *
                        (ipv4 ? PIMAddrSource.ENC_SOURCE_IPV4_BYTE_LENGTH : PIMAddrSource.ENC_SOURCE_IPV6_BYTE_LENGTH);
                checkInput(bb.array(), bb.position(), bb.limit() - bb.position(), required);

                // Now iterate through the joins for this group
                for (; njoins > 0; njoins--) {

                    PIMAddrSource src = new PIMAddrSource();
                    src.deserialize(bb);

                    jp.addJoinPrune(
                            src.getAddr().toIpPrefix(),
                            grp.getAddr().toIpPrefix(), true);
                }

                // Now iterate through the prunes for this group
                for (; nprunes > 0; nprunes--) {

                    PIMAddrSource src = new PIMAddrSource();
                    src.deserialize(bb);
                    jp.addJoinPrune(
                            src.getAddr().toIpPrefix(),
                            grp.getAddr().toIpPrefix(), false);
                }
            }

            return jp;
        };
    }

    @Override
    public String toString() {
        return toStringHelper(getClass())
                .add("upstreamAddr", upstreamAddr.toString())
                .add("holdTime", Short.toString(holdTime))
                .toString();
        // TODO: need to handle joinPrunes
    }
}
