package org.artisanlogiciel.games.minetest.net;

import org.artisanlogiciel.games.minetest.core.PacketException;
import org.artisanlogiciel.games.minetest.core.Serialize;

import java.util.ArrayList;

public class IncomingSplitBuffer {

    int m_seqnum;
    int m_chunk_count;
    int m_chunk_num;

    // number of chunks
    int m_got = 0;

    NetworkPacket m_list[] = null;
    BufferedPacket m_reassembled = null;

    BufferedPacket insert(NetworkPacket networkPacket)
            throws PacketException
    {

        byte[] buffer = networkPacket.getBuffer();
        int length = networkPacket.getLength();
        int offset = networkPacket.getOffset();

        int type = Serialize.readU8(buffer , offset, length);
        int seqnum = Serialize.readU16(buffer, offset + 1, length);
        // total number of chunk
        int chunk_count = Serialize.readU16(buffer, offset + 3, length);
        // this chunk number
        int chunk_num = Serialize.readU16(buffer, offset+ 5, length);

        System.out.println("Split length " + length + " type " + type + " seqnum " + seqnum + " chunk_num/chunk_count " + chunk_num + "/" + chunk_count );

        // move to next header
        networkPacket.addOffset(7);

        if (m_reassembled != null)
        {
            return m_reassembled;
        }

        if (m_list == null )
        {
            m_list = new NetworkPacket[chunk_count];
        }

        if ( chunk_num < chunk_count && (m_list[chunk_num] == null) )
        {
            m_list[chunk_num] = networkPacket;
            m_got ++;
        }
        //todo seqnum
        m_seqnum = seqnum;

        // fully obtained
        if ( m_got == chunk_count )
        {
            reassemble();
        }

        return m_reassembled;

    }

    private void reassemble()
    {
        // keep first header since result is a valid BufferedPacket
        int fullLength = BufferedPacket.BASE_HEADER_SIZE;
        for (NetworkPacket networkPacket : m_list )
        {
            fullLength += networkPacket.getLength() - networkPacket.getOffset();
        }
        byte[] reassembled = new byte[fullLength];
        NetworkPacket first = m_list[0];
        System.arraycopy(first.getBuffer(),0,reassembled,0,BufferedPacket.BASE_HEADER_SIZE);
        int offset = BufferedPacket.BASE_HEADER_SIZE;
        for (NetworkPacket networkPacket : m_list )
        {
            int dataLength = networkPacket.getLength() - networkPacket.getOffset();
            System.arraycopy(networkPacket.getBuffer(), networkPacket.getOffset(),reassembled,offset,dataLength);
            offset+=dataLength;
        }
        m_reassembled = new BufferedPacket(reassembled);

    }

}
