/**
   * Internal function get the total length of primary block to write on the buffer
   *
   * @param bundle Bundle to generate
   * @param dict Dictionary to get the offsets of the endpoint eids
   * @param primary PrimaryBlock data strucre object
   * @return Total numbers of Bytes required to write primary block
   */
  protected static int get_primary_len(final Bundle bundle, Dictionary dict, PrimaryBlock primary) {
    int primary_len = 0;
    int block_len = 0;
    primary.set_dictionary_length(0);
    primary.set_block_length(0);

    /*
     * We need to figure out the total length of the primary block,
     * except for the SDNVs used to encode flags and the length itself and
     * the one byte version field.
     *
     * First, we determine the size of the dictionary by first
     * figuring out all the unique strings, and in the process,
     * remembering their offsets and summing up their lengths
     * (including the null terminator for each).
     */

    dict.get_offsets(bundle.dest(), primary.dest_scheme_offset(), primary.dest_ssp_offset());

    block_len += SDNV.encoding_len(primary.dest_scheme_offset());
    block_len += SDNV.encoding_len(primary.dest_ssp_offset());

    dict.get_offsets(bundle.source(), primary.source_scheme_offset(), primary.source_ssp_offset());

    block_len += SDNV.encoding_len(primary.source_scheme_offset());
    block_len += SDNV.encoding_len(primary.source_ssp_offset());

    dict.get_offsets(
        bundle.replyto(), primary.replyto_scheme_offset(), primary.replyto_ssp_offset());

    block_len += SDNV.encoding_len(primary.replyto_scheme_offset());
    block_len += SDNV.encoding_len(primary.replyto_ssp_offset());

    dict.get_offsets(
        bundle.custodian(), primary.custodian_scheme_offset(), primary.custodian_ssp_offset());

    block_len += SDNV.encoding_len(primary.custodian_scheme_offset());
    block_len += SDNV.encoding_len(primary.custodian_ssp_offset());

    primary.set_dictionary_length(dict.dict_length());

    block_len += SDNV.encoding_len(bundle.creation_ts().seconds());
    block_len += SDNV.encoding_len(bundle.creation_ts().seqno());
    block_len += SDNV.encoding_len(bundle.expiration());

    block_len += SDNV.encoding_len(primary.dictionary_length_value());
    block_len += primary.dictionary_length_value();

    /*
     * If the bundle is a fragment, we need to include space for the
     * fragment offset and the original payload length.
     *
     * Note: Any changes to this protocol must be reflected into the
     * FragmentManager since it depends on this length when
     * calculating fragment sizes.
     */
    if (bundle.is_fragment()) {
      block_len += SDNV.encoding_len(bundle.frag_offset());
      block_len += SDNV.encoding_len(bundle.orig_length());
    }

    // Format the processing flags.
    primary.set_processing_flags(format_bundle_flags(bundle));

    primary.set_processing_flags(format_bundle_flags(bundle));
    primary.set_processing_flags(primary.processing_flags_value() | format_cos_flags(bundle));
    primary.set_processing_flags(primary.processing_flags_value() | format_srr_flags(bundle));

    /*
     * Finally, add up the initial preamble and the variable
     * length part.
     */

    primary.set_block_length(block_len);

    primary_len =
        (int)
            (1
                + SDNV.encoding_len(primary.processing_flags)
                + SDNV.encoding_len(primary.block_length())
                + primary.block_length_value());

    Log.d(TAG, "get_primary_len: for bundleid = " + bundle.bundleid() + ": " + primary_len);
    // Fill in the remaining values of 'primary' just for the sake of returning
    // a complete data structure.
    primary.set_version(BundleProtocol.CURRENT_VERSION);
    primary.set_creation_time(bundle.creation_ts().seconds());
    primary.set_creation_sequence(bundle.creation_ts().seqno());
    primary.set_lifetime(bundle.expiration());
    return primary_len;
  }
  /**
   * Generate primary block by encoding all the metadata of the primary block and copy to primary
   * block writeable buffer.
   *
   * @param bundle Bundle to generate
   * @param xmit_blocks xmit_blocks of the bundle
   * @param block Primary block of the bundle to generate and write to the writeable buffer
   */
  public void generate_primary(final Bundle bundle, BlockInfoVec xmit_blocks, BlockInfo block) {

    // point at the local dictionary
    Dictionary dict = xmit_blocks.dict();
    int primary_len = 0; // total length of the primary block
    PrimaryBlock primary = new PrimaryBlock();

    primary_len = get_primary_len(bundle, dict, primary);

    block.set_contents(new SerializableByteBuffer(primary_len));

    block.set_data_length((int) primary.block_length_value());
    block.set_data_offset((int) (primary_len - primary.block_length_value()));
    /*
     * Advance buf and decrement len as we go through the process.
     */
    IByteBuffer buf = block.writable_contents();
    int len = primary_len;

    Log.d(TAG, String.format("generating primary: length %s", primary_len));

    // Stick the version number in the first byte.
    buf.put((byte) BundleProtocol.CURRENT_VERSION);
    len -= 1;

    len -= write_sdnv(primary.processing_flags(), buf);
    len -= write_sdnv(primary.block_length(), buf);
    len -= write_sdnv(primary.dest_scheme_offset(), buf);
    len -= write_sdnv(primary.dest_ssp_offset(), buf);
    len -= write_sdnv(primary.source_scheme_offset(), buf);
    len -= write_sdnv(primary.source_ssp_offset(), buf);
    len -= write_sdnv(primary.replyto_scheme_offset(), buf);
    len -= write_sdnv(primary.replyto_ssp_offset(), buf);
    len -= write_sdnv(primary.custodian_scheme_offset(), buf);
    len -= write_sdnv(primary.custodian_ssp_offset(), buf);
    len -= write_sdnv(bundle.creation_ts().seconds(), buf);
    len -= write_sdnv(bundle.creation_ts().seqno(), buf);
    len -= write_sdnv(bundle.expiration(), buf);
    len -= write_sdnv(primary.dictionary_length(), buf);

    // Add the dictionary.
    Log.d(TAG, "Current Buf: " + buf.position());
    Log.d(TAG, "Dict length: " + dict.dict_length());
    Log.d(TAG, "Dict length: " + dict.dict_length());
    buf.put(dict.dict());
    // memcpy(buf, dict->dict(), dict->length());
    //        buf += dict->length();
    len -= dict.dict_length();
    Log.d(TAG, "Preparing len:" + len);
    /*
     * If the bundle is a fragment, stuff in SDNVs for the fragment
     * offset and original length.
     */

    if (bundle.is_fragment()) {
      len -= write_sdnv(bundle.frag_offset(), buf);
      Log.d(TAG, "Preparing len:" + len);

      len -= write_sdnv(bundle.orig_length(), buf);
      Log.d(TAG, "Preparing len:" + len);
    }
    /*
     * Asuming that get_primary_len is written correctly, len should
     * now be zero since we initialized it to primary_len at the
     * beginning of the function.
     */

    buf.position(0);
    assert (len == 0) : TAG + ": len not ==0";
    Log.e(TAG, "Current Len: " + len);
  }