/*
 * 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.LinkedHashMap;
import java.util.List;
import java.util.Map;

import uk.me.parabola.imgfmt.app.ImgFileWriter;

/**
 * POI subtype with a reference to MDR11.
 * These are sorted into groups based on the type, and contain the
 * subtype.
 *
 * The mdr9 section contains an index to this section based on the
 * the type groups.
 *
 * @author Steve Ratcliffe
 */
public class Mdr10 extends MdrMapSection {
	/** The maximum group number.  Note that this is 1 based, not 0 based. */
	private static final int MAX_GROUP_NUMBER = MdrUtils.MAX_GROUP;

	private List<List<Mdr10Record>> poiTypes = new ArrayList<>();

	private int numberOfPois;

	public Mdr10(MdrConfig config) {
		setConfig(config);
		while (poiTypes.size() <= MAX_GROUP_NUMBER)
			poiTypes.add(new ArrayList<>());
	}

	public void addPoiType(Mdr11Record poi) {
		Mdr10Record t = new Mdr10Record();

		int fullType = poi.getType();

		int group = MdrUtils.getGroupForPoi(fullType);
		if (group == 0)
			return;
		if (group == 1)
			t.setSubtype(MdrUtils.getTypeFromFullType(fullType)); // cities
		else {
			t.setSubtype(MdrUtils.getSubtypeFromFullType(fullType));
		}
		t.setMdr11ref(poi);
		poiTypes.get(group).add(t);
	}

	public void writeSectData(ImgFileWriter writer) {
		int count = 0;
		for (List<Mdr10Record> poiGroup : poiTypes) {
			if (poiGroup == null)
				continue;
			
			poiGroup.sort(null);

			String lastName = null;
			int lastSub = -1;
			for (Mdr10Record t : poiGroup) {

				count++;
				Mdr11Record mdr11ref = t.getMdr11ref();
				addIndexPointer(mdr11ref.getMapIndex(), count);
				
				writer.put1u(t.getSubtype());
				int offset = mdr11ref.getRecordNumber();

				// Top bit actually represents a non-repeated name.  ie if
				// the bit is not set, then the name is the same as the previous
				// record.
				String name = mdr11ref.getName();
				boolean isNew = !(name.equals(lastName) && (t.getSubtype() == lastSub));
				putPoiIndex(writer, offset, isNew);
				lastName = name;
				lastSub = t.getSubtype();
			}
		}
	}

	/**
	 * Get a list of the group sizes along with the group index number.
	 * @return A map that is guaranteed to iterate in the correct order for
	 * writing mdr9. The key is the group number and the value is the
	 * number of entries in that group.
	 */
	public Map<Integer, Integer> getGroupSizes() {
		Map<Integer, Integer> m = new LinkedHashMap<>();

		for (int group = 1; group <= MAX_GROUP_NUMBER; group++) {
			int size = poiTypes.get(group).size();
			if (size > 0)
				m.put(group, size);
		}
		return m;
	}

	/**
	 * This does not have a record size.
	 * @return Always zero to indicate that there is not a record size.
	 */
	public int getItemSize() {
		return 0;
	}

	protected int numberOfItems() {
		return numberOfPois;
	}

	public void setNumberOfPois(int numberOfPois) {
		this.numberOfPois = numberOfPois;
	}

	@Override
	protected void releaseMemory() {
		poiTypes = null;
	}

	public int getExtraValue() {
		// Nothing to do here
		return 0;
	}
}
