/*
 * Copyright 2018-present Open Networking Foundation
 *
 * 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.openstacktelemetry.codec;

import org.onlab.packet.IpAddress;
import org.onlab.packet.IpAddress.Version;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.TpPort;
import org.onlab.packet.VlanId;
import org.onosproject.net.DeviceId;
import org.onosproject.openstacktelemetry.api.ByteBufferCodec;
import org.onosproject.openstacktelemetry.api.FlowInfo;
import org.onosproject.openstacktelemetry.api.StatsInfo;
import org.onosproject.openstacktelemetry.impl.DefaultFlowInfo;

import java.nio.ByteBuffer;

/**
 * FlowInfo ByteBuffer Codec.
 */
public class TinaFlowInfoByteBufferCodec extends ByteBufferCodec<FlowInfo> {

    private static final int MESSAGE_SIZE = 88;
    private static final String OF_PREFIX = "of:";

    @Override
    public ByteBuffer encode(FlowInfo flowInfo) {

        ByteBuffer byteBuffer = ByteBuffer.allocate(MESSAGE_SIZE);
        int srcPort = 0;
        int dstPort = 0;

        String  deviceId = flowInfo.deviceId().toString();
        short switchId = (short) Integer.parseInt(deviceId.substring(3,
                                                  deviceId.length()), 16);

        if (flowInfo.srcPort() != null) {
            srcPort = flowInfo.srcPort().toInt();
        }

        if (flowInfo.dstPort() != null) {
            dstPort = flowInfo.dstPort().toInt();
        }

        byteBuffer.put(flowInfo.flowType())
                .putShort(switchId)
                .putInt(flowInfo.inputInterfaceId())
                .putInt(flowInfo.outputInterfaceId())
                .putShort(flowInfo.vlanId().toShort())
                .put(flowInfo.srcIp().address().toOctets())
                .put((byte) flowInfo.srcIp().prefixLength())
                .putShort((short) srcPort)
                .put(flowInfo.dstIp().address().toOctets())
                .put((byte) flowInfo.dstIp().prefixLength())
                .putShort((short) dstPort)
                .put(flowInfo.protocol())
                .put(flowInfo.srcMac().toBytes())
                .put(flowInfo.dstMac().toBytes());

        TinaStatsInfoByteBufferCodec statsInfoByteBufferCodec =
                new TinaStatsInfoByteBufferCodec();
        byteBuffer.put(statsInfoByteBufferCodec.encode(flowInfo.statsInfo()).array());

        return byteBuffer;
    }

    @Override
    public FlowInfo decode(ByteBuffer byteBuffer) {

        byte flowType = byteBuffer.get();
        String deviceIdStr = String.format("%016x", byteBuffer.getShort());
        DeviceId deviceId = DeviceId.deviceId(OF_PREFIX + deviceIdStr);
        int inputInterfaceId = byteBuffer.getInt();
        int outputInterfaceId = byteBuffer.getInt();
        VlanId vlanId = VlanId.vlanId(byteBuffer.getShort());
        IpAddress srcIp = IpAddress.valueOf(Version.INET, getIpv4Octets(byteBuffer));
        int srcPrefixLen = byteBuffer.get();
        TpPort srcPort = TpPort.tpPort((int) byteBuffer.getShort());
        IpAddress dstIp = IpAddress.valueOf(Version.INET, getIpv4Octets(byteBuffer));
        int dstPrefixLen = byteBuffer.get();
        TpPort dstPort = TpPort.tpPort((int) byteBuffer.getShort());

        byte protocol = byteBuffer.get();
        MacAddress srcMac = MacAddress.valueOf(getMacByteArray(byteBuffer));
        MacAddress dstMac = MacAddress.valueOf(getMacByteArray(byteBuffer));

        TinaStatsInfoByteBufferCodec statsInfoByteBufferCodec =
                new TinaStatsInfoByteBufferCodec();
        StatsInfo statsInfo = statsInfoByteBufferCodec.decode(byteBuffer);

        return new DefaultFlowInfo.DefaultBuilder()
                .withFlowType(flowType)
                .withDeviceId(deviceId)
                .withInputInterfaceId(inputInterfaceId)
                .withOutputInterfaceId(outputInterfaceId)
                .withVlanId(vlanId)
                .withSrcIp(IpPrefix.valueOf(srcIp, srcPrefixLen))
                .withSrcPort(srcPort)
                .withDstIp(IpPrefix.valueOf(dstIp, dstPrefixLen))
                .withDstPort(dstPort)
                .withProtocol(protocol)
                .withSrcMac(srcMac)
                .withDstMac(dstMac)
                .withStatsInfo(statsInfo)
                .build();
    }

    /**
     * Obtains IPv4 Octets from ByteBuffer.
     *
     * @param buffer byte buffer
     * @return Ipv4 Octets
     */
    private byte[] getIpv4Octets(ByteBuffer buffer) {
        byte[] octets = new byte[4];
        for (int i = 0; i < octets.length; i++) {
            octets[i] = buffer.get();
        }
        return octets;
    }

    /**
     * Obtains MAC address byte array from ByteBuffer.
     *
     * @param buffer byte buffer
     * @return MAC address byte array
     */
    private byte[] getMacByteArray(ByteBuffer buffer) {
        byte[] array = new byte[6];
        for (int i = 0; i < array.length; i++) {
            array[i] = buffer.get();
        }
        return array;
    }
}
