package tim.prune.function.autoplay;

import tim.prune.data.DataPoint;
import tim.prune.data.Timestamp;

/**
 * Holds the information about a single point required for the sorting
 */
public class PointInfo implements Comparable<PointInfo>
{
	/** Timestamp of the point, if any */
	private final Timestamp _timestamp;
	/** Point index in the track */
	private final int _pointIndex;
	/** Segment flag of point */
	private final boolean _segmentFlag;


	/**
	 * Constructor
	 * @param inPoint point from track
	 * @param inIndex index of point in track
	 */
	public PointInfo(DataPoint inPoint, int inIndex)
	{
		if (inPoint.hasTimestamp()) {
			_timestamp = inPoint.getTimestamp();
		}
		else if (inPoint.getPhoto() != null && inPoint.getPhoto().hasTimestamp()) {
			_timestamp = inPoint.getPhoto().getTimestamp();
		}
		else {
			_timestamp = null;
		}
		_pointIndex = inIndex;
		_segmentFlag = inPoint.getSegmentStart();
	}

	/** @return timestamp */
	public Timestamp getTimestamp() {
		return _timestamp;
	}

	/** @return point index */
	public int getIndex() {
		return _pointIndex;
	}

	/** @return segment flag */
	public boolean getSegmentFlag() {
		return _segmentFlag;
	}

	/**
	 * Sort two objects by timestamp and if times equal then by point index
	 */
	public int compareTo(PointInfo inOther)
	{
		long timeDiff = 0;
		final boolean thisHasTime = (_timestamp != null);
		final boolean otherHasTime = (inOther._timestamp != null);
		if (thisHasTime && otherHasTime)
		{
			timeDiff = _timestamp.getMillisecondsSince(inOther._timestamp);
		}
		else if (thisHasTime)
		{
			timeDiff = -1; // points without time to the end
		}
		else if (otherHasTime)
		{
			timeDiff = 1;
		}
		// If the times are equal (or both missing) then use the point index
		if (timeDiff == 0) {
			return _pointIndex - inOther._pointIndex;
		}
		// Otherwise, compare by time
		return (timeDiff < 0 ? -1 : 1);
	}

	@Override
	public boolean equals(Object inOther)
	{
		if (!(inOther instanceof PointInfo)) {
			return false;
		}

		PointInfo other = (PointInfo) inOther;
		if (_pointIndex != other._pointIndex) return false;
		final boolean thisHasTime = (_timestamp != null);
		final boolean otherHasTime = (other._timestamp != null);
		if (thisHasTime != otherHasTime) {return false;}
		if (!thisHasTime && !otherHasTime) {return true;}
		return _timestamp.isEqual(other._timestamp);
	}
}
