static int writeHeaderBuffer(final MapWriterConfiguration configuration,
                                 final TileBasedDataProcessor dataProcessor, final ByteBuffer containerHeaderBuffer) {
        LOGGER.fine("writing header");
        LOGGER.fine("Bounding box for file: " + dataProcessor.getBoundingBox().toString());

        // write file header
        // MAGIC BYTE
        byte[] magicBytes = MAGIC_BYTE.getBytes(UTF8_CHARSET);
        containerHeaderBuffer.put(magicBytes);

        // HEADER SIZE: Write dummy pattern as header size. It will be replaced
        // later in time
        int headerSizePosition = containerHeaderBuffer.position();
        containerHeaderBuffer.putInt(DUMMY_INT);

        // FILE VERSION
        containerHeaderBuffer.putInt(configuration.getFileSpecificationVersion());

        // FILE SIZE: Write dummy pattern as file size. It will be replaced
        // later in time
        containerHeaderBuffer.putLong(DUMMY_LONG);
        // DATE OF CREATION
        containerHeaderBuffer.putLong(System.currentTimeMillis());

        // BOUNDING BOX
        containerHeaderBuffer.putInt(LatLongUtils.degreesToMicrodegrees(dataProcessor.getBoundingBox().minLatitude));
        containerHeaderBuffer.putInt(LatLongUtils.degreesToMicrodegrees(dataProcessor.getBoundingBox().minLongitude));
        containerHeaderBuffer.putInt(LatLongUtils.degreesToMicrodegrees(dataProcessor.getBoundingBox().maxLatitude));
        containerHeaderBuffer.putInt(LatLongUtils.degreesToMicrodegrees(dataProcessor.getBoundingBox().maxLongitude));

        // TILE SIZE
        containerHeaderBuffer.putShort((short) Constants.DEFAULT_TILE_SIZE);

        // PROJECTION
        writeUTF8(PROJECTION, containerHeaderBuffer);

        // check whether zoom start is a valid zoom level

        // FLAGS
        containerHeaderBuffer.put(infoByteOptmizationParams(configuration));

        // MAP START POSITION
        LatLong mapStartPosition = configuration.getMapStartPosition();
        if (mapStartPosition != null) {
            containerHeaderBuffer.putInt(LatLongUtils.degreesToMicrodegrees(mapStartPosition.latitude));
            containerHeaderBuffer.putInt(LatLongUtils.degreesToMicrodegrees(mapStartPosition.longitude));
        }

        // MAP START ZOOM
        if (configuration.hasMapStartZoomLevel()) {
            containerHeaderBuffer.put((byte) configuration.getMapStartZoomLevel());
        }

        // PREFERRED LANGUAGE
        if (configuration.getPreferredLanguages() != null && !configuration.getPreferredLanguages().isEmpty()) {
            String langStr = "";
            for (String preferredLanguage : configuration.getPreferredLanguages()) {
                langStr += (langStr.length() > 0 ? "," : "") + preferredLanguage;
            }
            writeUTF8(langStr, containerHeaderBuffer);
        }

        // COMMENT
        if (configuration.getComment() != null) {
            writeUTF8(configuration.getComment(), containerHeaderBuffer);
        }

        // CREATED WITH
        writeUTF8(configuration.getWriterVersion(), containerHeaderBuffer);

        OSMTagMapping mapping = configuration.getTagMapping();

        // AMOUNT POI TAGS
        containerHeaderBuffer.putShort((short) mapping.getOptimizedPoiIds().size());
        // POI TAGS
        // retrieves tag ids in order of frequency, most frequent come first
        for (short tagId : mapping.getOptimizedPoiIds().keySet()) {
            OSMTag tag = mapping.getPoiTag(tagId);
            writeUTF8(tag.tagKey(), containerHeaderBuffer);
        }

        // AMOUNT OF WAY TAGS
        containerHeaderBuffer.putShort((short) mapping.getOptimizedWayIds().size());

        // WAY TAGS
        for (short tagId : mapping.getOptimizedWayIds().keySet()) {
            OSMTag tag = mapping.getWayTag(tagId);
            writeUTF8(tag.tagKey(), containerHeaderBuffer);
        }

        // AMOUNT OF ZOOM INTERVALS
        int numberOfZoomIntervals = dataProcessor.getZoomIntervalConfiguration().getNumberOfZoomIntervals();
        containerHeaderBuffer.put((byte) numberOfZoomIntervals);

        // SET MARK OF THIS BUFFER AT POSITION FOR WRITING ZOOM INTERVAL CONFIG
        containerHeaderBuffer.mark();
        // ZOOM INTERVAL CONFIGURATION: SKIP COMPUTED AMOUNT OF BYTES
        containerHeaderBuffer.position(containerHeaderBuffer.position() + SIZE_ZOOMINTERVAL_CONFIGURATION
                * numberOfZoomIntervals);

        // now write header size
        // -4 bytes of header size variable itself
        int headerSize = containerHeaderBuffer.position() - headerSizePosition - BYTES_INT;
        containerHeaderBuffer.putInt(headerSizePosition, headerSize);

        return containerHeaderBuffer.position();
    }
@Test
    public void testWriteHeaderBuffer() {
        ByteBuffer headerBuffer = ByteBuffer.allocate(MapFileWriter.HEADER_BUFFER_SIZE);
        int headerLength = MapFileWriter.writeHeaderBuffer(this.configuration, this.dataProcessor, headerBuffer);

        // expected header length
        // 20 + 4 + 4 + 8 + 8 + 16 + 2
        // + 9 ("Mercator")
        // + 1 + 8 + 1
        // + 6 ("en,de")
        // + 17 ("i love mapsforge")
        // + 5("test")
        // + 2 + 19 ("amenity=university")
        // + 2 + 14 + 18 ("natural=beach", natural=coastline")
        // + 1
        // + 3 * (3 + 8 + 8)
        // == 222
        Assert.assertEquals(222, headerLength);
    }