/*
 * Copyright 2014 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;

import java.nio.ByteBuffer;
import java.util.Arrays;

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

/**
 * Representation of an ARP Packet.
 */
public class ARP extends BasePacket {
    public static final short HW_TYPE_ETHERNET = 0x1;

    public static final short PROTO_TYPE_IP = 0x800;

    public static final short OP_REQUEST = 0x1;
    public static final short OP_REPLY = 0x2;
    public static final short OP_RARP_REQUEST = 0x3;
    public static final short OP_RARP_REPLY = 0x4;

    public static final short INITIAL_HEADER_LENGTH = 8;

    protected short hardwareType;
    protected short protocolType;
    protected byte hardwareAddressLength;
    protected byte protocolAddressLength;
    protected short opCode;
    protected byte[] senderHardwareAddress;
    protected byte[] senderProtocolAddress;
    protected byte[] targetHardwareAddress;
    protected byte[] targetProtocolAddress;

    /**
     * @return the hardwareType
     */
    public short getHardwareType() {
        return this.hardwareType;
    }

    /**
     * @param hwType
     *            the hardwareType to set
     * @return this
     */
    public ARP setHardwareType(final short hwType) {
        this.hardwareType = hwType;
        return this;
    }

    /**
     * @return the protocolType
     */
    public short getProtocolType() {
        return this.protocolType;
    }

    /**
     * @param protoType
     *            the protocolType to set
     * @return this
     */
    public ARP setProtocolType(final short protoType) {
        this.protocolType = protoType;
        return this;
    }

    /**
     * @return the hardwareAddressLength
     */
    public byte getHardwareAddressLength() {
        return this.hardwareAddressLength;
    }

    /**
     * @param hwAddressLength
     *            the hardwareAddressLength to set
     * @return this
     */
    public ARP setHardwareAddressLength(final byte hwAddressLength) {
        this.hardwareAddressLength = hwAddressLength;
        return this;
    }

    /**
     * @return the protocolAddressLength
     */
    public byte getProtocolAddressLength() {
        return this.protocolAddressLength;
    }

    /**
     * @param protoAddressLength
     *            the protocolAddressLength to set
     * @return this
     */
    public ARP setProtocolAddressLength(final byte protoAddressLength) {
        this.protocolAddressLength = protoAddressLength;
        return this;
    }

    /**
     * @return the opCode
     */
    public short getOpCode() {
        return this.opCode;
    }

    /**
     * @param op
     *            the opCode to set
     * @return this
     */
    public ARP setOpCode(final short op) {
        this.opCode = op;
        return this;
    }

    /**
     * @return the senderHardwareAddress
     */
    public byte[] getSenderHardwareAddress() {
        return this.senderHardwareAddress;
    }

    /**
     * @param senderHWAddress
     *            the senderHardwareAddress to set
     * @return this
     */
    public ARP setSenderHardwareAddress(final byte[] senderHWAddress) {
        this.senderHardwareAddress = senderHWAddress;
        return this;
    }

    /**
     * @return the senderProtocolAddress
     */
    public byte[] getSenderProtocolAddress() {
        return this.senderProtocolAddress;
    }

    /**
     * @param senderProtoAddress
     *            the senderProtocolAddress to set
     * @return this
     */
    public ARP setSenderProtocolAddress(final byte[] senderProtoAddress) {
        this.senderProtocolAddress = senderProtoAddress;
        return this;
    }

    public ARP setSenderProtocolAddress(final int address) {
        this.senderProtocolAddress = ByteBuffer.allocate(4).putInt(address)
                .array();
        return this;
    }

    /**
     * @return the targetHardwareAddress
     */
    public byte[] getTargetHardwareAddress() {
        return this.targetHardwareAddress;
    }

    /**
     * @param targetHWAddress
     *            the targetHardwareAddress to set
     * @return this
     */
    public ARP setTargetHardwareAddress(final byte[] targetHWAddress) {
        this.targetHardwareAddress = targetHWAddress;
        return this;
    }

    /**
     * @return the targetProtocolAddress
     */
    public byte[] getTargetProtocolAddress() {
        return this.targetProtocolAddress;
    }

    /**
     * @return True if gratuitous ARP (SPA = TPA), false otherwise
     */
    public boolean isGratuitous() {
        assert this.senderProtocolAddress.length == this.targetProtocolAddress.length;

        int indx = 0;
        while (indx < this.senderProtocolAddress.length) {
            if (this.senderProtocolAddress[indx] != this.targetProtocolAddress[indx]) {
                return false;
            }
            indx++;
        }

        return true;
    }

    /**
     * @param targetProtoAddress
     *            the targetProtocolAddress to set
     * @return this
     */
    public ARP setTargetProtocolAddress(final byte[] targetProtoAddress) {
        this.targetProtocolAddress = targetProtoAddress;
        return this;
    }

    public ARP setTargetProtocolAddress(final int address) {
        this.targetProtocolAddress = ByteBuffer.allocate(4).putInt(address)
                .array();
        return this;
    }

    @Override
    public byte[] serialize() {
        final int length = 8 + 2 * (0xff & this.hardwareAddressLength) + 2
                * (0xff & this.protocolAddressLength);
        final byte[] data = new byte[length];
        final ByteBuffer bb = ByteBuffer.wrap(data);
        bb.putShort(this.hardwareType);
        bb.putShort(this.protocolType);
        bb.put(this.hardwareAddressLength);
        bb.put(this.protocolAddressLength);
        bb.putShort(this.opCode);
        bb.put(this.senderHardwareAddress, 0, 0xff & this.hardwareAddressLength);
        bb.put(this.senderProtocolAddress, 0, 0xff & this.protocolAddressLength);
        bb.put(this.targetHardwareAddress, 0, 0xff & this.hardwareAddressLength);
        bb.put(this.targetProtocolAddress, 0, 0xff & this.protocolAddressLength);
        return data;
    }

    @Override
    public IPacket deserialize(final byte[] data, final int offset,
                               final int length) {
        final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
        this.hardwareType = bb.getShort();
        this.protocolType = bb.getShort();
        this.hardwareAddressLength = bb.get();
        this.protocolAddressLength = bb.get();
        this.opCode = bb.getShort();
        this.senderHardwareAddress = new byte[0xff & this.hardwareAddressLength];
        bb.get(this.senderHardwareAddress, 0, this.senderHardwareAddress.length);
        this.senderProtocolAddress = new byte[0xff & this.protocolAddressLength];
        bb.get(this.senderProtocolAddress, 0, this.senderProtocolAddress.length);
        this.targetHardwareAddress = new byte[0xff & this.hardwareAddressLength];
        bb.get(this.targetHardwareAddress, 0, this.targetHardwareAddress.length);
        this.targetProtocolAddress = new byte[0xff & this.protocolAddressLength];
        bb.get(this.targetProtocolAddress, 0, this.targetProtocolAddress.length);
        return this;
    }

    /*
     * (non-Javadoc)
     *
     * @see java.lang.Object#hashCode()
     */
    @Override
    public int hashCode() {
        final int prime = 13121;
        int result = super.hashCode();
        result = prime * result + this.hardwareAddressLength;
        result = prime * result + this.hardwareType;
        result = prime * result + this.opCode;
        result = prime * result + this.protocolAddressLength;
        result = prime * result + this.protocolType;
        result = prime * result + Arrays.hashCode(this.senderHardwareAddress);
        result = prime * result + Arrays.hashCode(this.senderProtocolAddress);
        result = prime * result + Arrays.hashCode(this.targetHardwareAddress);
        result = prime * result + Arrays.hashCode(this.targetProtocolAddress);
        return result;
    }

    /*
     * (non-Javadoc)
     *
     * @see java.lang.Object#equals(java.lang.Object)
     */
    @Override
    public boolean equals(final Object obj) {
        if (this == obj) {
            return true;
        }
        if (!super.equals(obj)) {
            return false;
        }
        if (!(obj instanceof ARP)) {
            return false;
        }
        final ARP other = (ARP) obj;
        if (this.hardwareAddressLength != other.hardwareAddressLength) {
            return false;
        }
        if (this.hardwareType != other.hardwareType) {
            return false;
        }
        if (this.opCode != other.opCode) {
            return false;
        }
        if (this.protocolAddressLength != other.protocolAddressLength) {
            return false;
        }
        if (this.protocolType != other.protocolType) {
            return false;
        }
        if (!Arrays.equals(this.senderHardwareAddress,
                other.senderHardwareAddress)) {
            return false;
        }
        if (!Arrays.equals(this.senderProtocolAddress,
                other.senderProtocolAddress)) {
            return false;
        }
        if (!Arrays.equals(this.targetHardwareAddress,
                other.targetHardwareAddress)) {
            return false;
        }
        if (!Arrays.equals(this.targetProtocolAddress,
                other.targetProtocolAddress)) {
            return false;
        }
        return true;
    }

    /**
     * Builds an ARP reply based on a request.
     *
     * @param srcIp the IP address to use as the reply source
     * @param srcMac the MAC address to use as the reply source
     * @param request the ARP request we got
     * @return an Ethernet frame containing the ARP reply
     */
    public static Ethernet buildArpReply(Ip4Address srcIp, MacAddress srcMac,
            Ethernet request) {

        Ethernet eth = new Ethernet();
        eth.setDestinationMACAddress(request.getSourceMAC());
        eth.setSourceMACAddress(srcMac);
        eth.setEtherType(Ethernet.TYPE_ARP);
        eth.setVlanID(request.getVlanID());

        ARP arp = new ARP();
        arp.setOpCode(ARP.OP_REPLY);
        arp.setProtocolType(ARP.PROTO_TYPE_IP);
        arp.setHardwareType(ARP.HW_TYPE_ETHERNET);

        arp.setProtocolAddressLength((byte) Ip4Address.BYTE_LENGTH);
        arp.setHardwareAddressLength((byte) Ethernet.DATALAYER_ADDRESS_LENGTH);
        arp.setSenderHardwareAddress(srcMac.toBytes());
        arp.setTargetHardwareAddress(request.getSourceMACAddress());

        arp.setTargetProtocolAddress(((ARP) request.getPayload())
                                             .getSenderProtocolAddress());
        arp.setSenderProtocolAddress(srcIp.toInt());

        eth.setPayload(arp);
        return eth;
    }

    /**
     * Deserializer function for ARP packets.
     *
     * @return deserializer function
     */
    public static Deserializer<ARP> deserializer() {
        return (data, offset, length) -> {
            checkInput(data, offset, length, INITIAL_HEADER_LENGTH);

            ARP arp = new ARP();
            final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
            arp.setHardwareType(bb.getShort());
            arp.setProtocolType(bb.getShort());

            byte hwAddressLength = bb.get();
            arp.setHardwareAddressLength(hwAddressLength);

            byte protocolAddressLength = bb.get();
            arp.setProtocolAddressLength(protocolAddressLength);
            arp.setOpCode(bb.getShort());

            // Check we have enough space for the addresses
            checkHeaderLength(length, INITIAL_HEADER_LENGTH +
                    2 * hwAddressLength +
                    2 * protocolAddressLength);

            arp.senderHardwareAddress = new byte[0xff & hwAddressLength];
            bb.get(arp.senderHardwareAddress, 0, arp.senderHardwareAddress.length);
            arp.senderProtocolAddress = new byte[0xff & protocolAddressLength];
            bb.get(arp.senderProtocolAddress, 0, arp.senderProtocolAddress.length);
            arp.targetHardwareAddress = new byte[0xff & hwAddressLength];
            bb.get(arp.targetHardwareAddress, 0, arp.targetHardwareAddress.length);
            arp.targetProtocolAddress = new byte[0xff & protocolAddressLength];
            bb.get(arp.targetProtocolAddress, 0, arp.targetProtocolAddress.length);

            return arp;
        };
    }

    @Override
    public String toString() {
        return toStringHelper(getClass())
                .add("hardwareType", Short.toString(hardwareType))
                .add("protocolType", Short.toString(protocolType))
                .add("hardwareAddressLength", Byte.toString(hardwareAddressLength))
                .add("protocolAddressLength", Byte.toString(protocolAddressLength))
                .add("opCode", Short.toString(opCode))
                .add("senderHardwareAddress", Arrays.toString(senderHardwareAddress))
                .add("senderProtocolAddress", Arrays.toString(senderProtocolAddress))
                .add("targetHardwareAddress", Arrays.toString(targetHardwareAddress))
                .add("targetProtocolAddress", Arrays.toString(targetProtocolAddress))
                .toString();
    }
}
