package org.mwc.debrief.core.gpx.mappers;

import java.math.BigDecimal;
import java.util.GregorianCalendar;
import java.util.List;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.JAXBIntrospector;
import javax.xml.bind.Unmarshaller;
import javax.xml.datatype.XMLGregorianCalendar;

import org.eclipse.core.runtime.Status;
import org.mwc.cmap.core.CorePlugin;
import org.mwc.debrief.core.gpx.FixExtensionType;
import org.mwc.debrief.core.loaders.DebriefJaxbContextAware;
import org.w3c.dom.Node;

import Debrief.Wrappers.FixWrapper;
import MWC.GUI.Properties.LocationPropertyEditor;
import MWC.GenericData.HiResDate;
import MWC.GenericData.WorldLocation;
import MWC.TacticalData.Fix;

import com.topografix.gpx.v11.ExtensionsType;
import com.topografix.gpx.v11.WptType;

/**
 * @author Aravind R. Yarram <yaravind@gmail.com>
 * @date August 21, 2012
 * @category gpx
 * 
 */
public class FixMapper implements DebriefJaxbContextAware
{
	private JAXBContext debriefContext;
	private static final BigDecimal MINUS_ONE = new BigDecimal("-1");

	public FixWrapper fromGpx(WptType trackType)
	{
		Fix fix = new Fix();

		WorldLocation val = new WorldLocation(trackType.getLat(), trackType.getLon(), convertElevationToDepth(trackType.getEle()));
		fix.setLocation(val);

		XMLGregorianCalendar time = trackType.getTime();
		GregorianCalendar calendar = time.toGregorianCalendar();
		fix.setTime(new HiResDate(calendar.getTime()));// TODO handle milli secs

		FixWrapper trackPoint = new FixWrapper(fix);

		ExtensionsType extensions = trackType.getExtensions();
		if (extensions != null)
		{
			List<Object> any = extensions.getAny();
			Unmarshaller unmarshaller;
			try
			{
				unmarshaller = debriefContext.createUnmarshaller();
				Object object = unmarshaller.unmarshal((Node) any.get(0));
				FixExtensionType fixExtension = (FixExtensionType) JAXBIntrospector.getValue(object);

				trackPoint.setCourse(Double.valueOf(fixExtension.getCourse()).doubleValue());
				trackPoint.setLabel(fixExtension.getLabel());
				trackPoint.setSpeed(Double.valueOf(fixExtension.getSpeed()).doubleValue());
				LocationPropertyEditor locationConverter = new LocationPropertyEditor();
				locationConverter.setAsText(fixExtension.getLabelLocation().value());
				trackPoint.setLabelLocation((Integer) locationConverter.getValue());
				trackPoint.setArrowShowing(fixExtension.isArrowShowing());
				trackPoint.setLabelShowing(fixExtension.isLabelShowing());
				trackPoint.setLineShowing(fixExtension.isLineShowing());
				trackPoint.setSymbolShowing(fixExtension.isSymbolShowing());
				trackPoint.setVisible(fixExtension.isVisible());
			}
			catch (JAXBException e)
			{
				CorePlugin.logError(Status.ERROR, "Error while mapping Track from GPX", e);
			}
		}

		return trackPoint;
	}

	/**
	 * Debrief and its datasets currently represent the 'z' dimension as Depth.
	 * GPX has elevation, so clearly we'll need to invert this data - positive
	 * depths in Debrief will be stored as negative elevations.
	 */
	private BigDecimal convertElevationToDepth(BigDecimal elevation)
	{
		return elevation.multiply(MINUS_ONE);
	}

	@Override
	public void setJaxbContext(JAXBContext ctx)
	{
		debriefContext = ctx;
	}
	/*
	 * private BigDecimal convertDepthToElevation(BigDecimal depth) { return
	 * depth.multiply(MINUS_ONE); }
	 */
}

@@ -1194,16 +1194,151 @@
 x();%0D%0A%0D%0A
+%09%09// we may not have a depth, better check%0D%0A%09%09BigDecimal ele = trackType.getEle();%0D%0A%09%09if (ele == null)%0D%0A%09%09%09ele = new BigDecimal(0);%0D%0A%0D%0A
 %09%09WorldL
@@ -1388,17 +1388,22 @@
 etLat(),
- 
+%0D%0A%09%09%09%09
 trackTyp
@@ -1438,34 +1438,19 @@
 ToDepth(
-trackType.getEle()
+ele
 ));%0D%0A%09%09f
@@ -1473,16 +1473,38 @@
 al);%0D%0A%0D%0A
+%09%09HiResDate theDate;%0D%0A
 %09%09XMLGre
@@ -1547,16 +1547,43 @@
 ime();%0D%0A
+%09%09if (time != null)%0D%0A%09%09%7B%0D%0A%09
 %09%09Gregor
@@ -1640,20 +1640,19 @@
 %0D%0A%09%09
-fix.setTime(
+%09theDate = 
 new 
@@ -1684,35 +1684,193 @@
 e())
-);// TODO handle milli secs
+;%0D%0A%09%09%7D%0D%0A%09%09else%0D%0A%09%09%7B%0D%0A%09%09%09CorePlugin.logError(Status.WARNING, %22GPX Data is missing time data. current date to be used%22, null);%0D%0A%09%09%09theDate = new HiResDate();%0D%0A%09%09%7D%0D%0A%09%09fix.setTime(theDate);
 %0D%0A%0D%0A
@@ -2290,16 +2290,24 @@
 ospector
+%0D%0A%09%09%09%09%09%09
 .getValu
@@ -2385,16 +2385,24 @@
 ourse())
+%0D%0A%09%09%09%09%09%09
 .doubleV
@@ -2525,16 +2525,24 @@
 Speed())
+%0D%0A%09%09%09%09%09%09
 .doubleV
@@ -3203,17 +3203,24 @@
 om GPX%22,
- 
+%0D%0A%09%09%09%09%09%09
 e);%0D%0A%09%09%09

handle missing elevation/time data