/*
* Copyright (C) 2009.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 or
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
package uk.me.parabola.imgfmt.app.mdr;
import java.util.ArrayList;
import java.util.List;
import uk.me.parabola.imgfmt.app.ImgFileWriter;
import uk.me.parabola.imgfmt.app.srt.SortKey;
import uk.me.parabola.imgfmt.app.trergn.Point;
/**
* Holds all the POIs, including cities. Arranged alphabetically by
* the name.
*
* @author Steve Ratcliffe
*/
public class Mdr11 extends MdrMapSection {
private List<Mdr11Record> pois = new ArrayList<>();
private Mdr10 mdr10;
public Mdr11(MdrConfig config) {
setConfig(config);
}
public Mdr11Record addPoi(int mapIndex, Point point, String name, int strOff) {
Mdr11Record poi = new Mdr11Record();
poi.setMapIndex(mapIndex);
poi.setPointIndex(point.getNumber());
poi.setSubdiv(point.getSubdiv().getNumber());
poi.setLblOffset(point.getLabel().getOffset());
poi.setName(name);
poi.setStrOffset(strOff);
pois.add(poi);
return poi;
}
/**
* Sort and fill in the mdr10 information.
*
* The POI index contains individual references to POI by subdiv and index, so they are not
* de-duplicated in the index in the same way that streets and cities are.
*/
protected void preWriteImpl() {
List<SortKey<Mdr11Record>> keys = MdrUtils.sortList(getConfig().getSort(), pois);
pois.clear();
for (SortKey<Mdr11Record> sk : keys) {
Mdr11Record poi = sk.getObject();
mdr10.addPoiType(poi);
pois.add(poi);
}
}
public void writeSectData(ImgFileWriter writer) {
int count = 1;
boolean hasStrings = hasFlag(2);
for (Mdr11Record poi : pois) {
addIndexPointer(poi.getMapIndex(), count);
poi.setRecordNumber(count++);
putMapIndex(writer, poi.getMapIndex());
writer.put((byte) poi.getPointIndex());
writer.putChar((char) poi.getSubdiv());
writer.put3(poi.getLblOffset());
if (poi.isCity())
putRegionIndex(writer, poi.getRegionIndex());
else
putCityIndex(writer, poi.getCityIndex(), true);
if (hasStrings)
putStringOffset(writer, poi.getStrOffset());
}
}
public int getItemSize() {
PointerSizes sizes = getSizes();
int size = sizes.getMapSize() + 6 + sizes.getCitySizeFlagged();
if (hasFlag(0x2))
size += sizes.getStrOffSize();
return size;
}
protected int numberOfItems() {
return pois.size();
}
public int getNumberOfPois() {
return getNumberOfItems();
}
public int getExtraValue() {
int mdr11flags = 0x11;
PointerSizes sizes = getSizes();
// two bit field for city bytes. minimum size of 2
int citySize = sizes.getCitySizeFlagged();
if (citySize > 2)
mdr11flags |= (citySize-2) << 2;
if (isForDevice())
mdr11flags |= 0x80;
else
mdr11flags |= 0x2;
return mdr11flags;
}
public List<Mdr8Record> getIndex() {
List<Mdr8Record> list = new ArrayList<>();
for (int number = 1; number <= pois.size(); number += 10240) {
String prefix = getPrefixForRecord(number);
// need to step back to find the first...
int rec = number;
while (rec > 1) {
String p = getPrefixForRecord(rec);
if (!p.equals(prefix)) {
rec++;
break;
}
rec--;
}
Mdr12Record indexRecord = new Mdr12Record();
indexRecord.setPrefix(prefix);
indexRecord.setRecordNumber(rec);
list.add(indexRecord);
}
return list;
}
/**
* Get the prefix of the name at the given record.
* @param number The record number.
* @return The first 4 (or whatever value is set) characters of the street
* name.
*/
private String getPrefixForRecord(int number) {
Mdr11Record record = pois.get(number-1);
int endIndex = MdrUtils.POI_INDEX_PREFIX_LEN;
String name = record.getName();
if (endIndex > name.length()) {
StringBuilder sb = new StringBuilder(name);
while (sb.length() < endIndex)
sb.append('\0');
name = sb.toString();
}
return name.substring(0, endIndex);
}
public void setMdr10(Mdr10 mdr10) {
this.mdr10 = mdr10;
}
public void releaseMemory() {
pois = null;
mdr10 = null;
}
public List<Mdr11Record> getPois() {
return new ArrayList<>(pois);
}
}