/*
 * Copyright (C) 2006 Steve Ratcliffe
 * 
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License 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.
 * 
 * 
 * Author: Steve Ratcliffe
 * Create date: 09-Dec-2006
 */
package uk.me.parabola.imgfmt.app.trergn;

import java.io.IOException;
import java.io.OutputStream;

import uk.me.parabola.imgfmt.app.Coord;
import uk.me.parabola.imgfmt.app.ImgFileWriter;
import uk.me.parabola.imgfmt.app.lbl.POIRecord;

/**
 * Represents a particular point object on a map.  A point has a type (town
 * restaurant etc) and a location as well as a name.
 *
 * A point belongs to a particular subdivision and cannot be interpreted without
 * it as all details are relative to the subdivision.
 *
 * @author Steve Ratcliffe
 */
public class Point extends MapObject {
	// Points can link to a POIRecord
	private POIRecord poi;

	public Point(Subdivision div) {
		setSubdiv(div);
	}

	/**
	 * Format and write the contents of the object to the given
	 * file.
	 *
	 * @param file A reference to the file that should be written to.
	 */
	public void write(ImgFileWriter file) {
		boolean hasSubtype = false;
		int type = getType();
		int subtype = 0;
		if (type > 0xff) {
			if((type & 0xff) != 0) {
			    hasSubtype = true;
			    subtype = type & 0xff;
			}
			type >>= 8;
		}

		file.put1u(type);

		int off = getLabel().getOffset();
		if (poi != null) {
			off = poi.getOffset();
			off |= 0x400000;
		}
		if (hasSubtype)
			off |= 0x800000;

		file.put3u(off);
		file.put2s(getDeltaLong());
		file.put2s(getDeltaLat());
		if (hasSubtype)
			file.put1u(subtype);
	}

	/*
	 * write the point to an OutputStream - only use for outputting
	 * points with extended (3 byte) types.
	 *
	 */
	public void write(OutputStream stream) throws IOException {
		assert hasExtendedType();
		int type = getType();
		int labelOff = getLabel().getOffset();
		byte[] extraBytes = getExtTypeExtraBytes();

		if (poi != null) {
			labelOff = poi.getOffset();
			labelOff |= 0x400000;
		}
		if(labelOff != 0)
			type |= 0x20;		// has label
		if(extraBytes != null)
			type |= 0x80;		// has extra bytes
		stream.write(type >> 8);
		stream.write(type);

		int deltaLong = getDeltaLong();
		int deltaLat = getDeltaLat();
		stream.write(deltaLong);
		stream.write(deltaLong >> 8);
		stream.write(deltaLat);
		stream.write(deltaLat >> 8);

		if(labelOff != 0) {
			stream.write(labelOff);
			stream.write(labelOff >> 8);
			stream.write(labelOff >> 16);
		}

		if(extraBytes != null)
			stream.write(extraBytes);
	}

	public void setPOIRecord(POIRecord poirecord) {
		this.poi = poirecord;
	}

	public POIRecord getPOIRecord() {
		if (poi == null)
			return new POIRecord();
		return poi;
	}

	public Coord getLocation() {
		int shift = getSubdiv().getShift();
		Coord co = new Coord(getSubdiv().getLatitude() + (getDeltaLat() << shift), 
				getSubdiv().getLongitude() + (getDeltaLong() << shift) );
		return co;
	}
}
