/*
 * JaamSim Discrete Event Simulation
 * Copyright (C) 2013 Ausenco Engineering Canada Inc.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * 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 com.jaamsim.DisplayModels;

import com.jaamsim.math.Vec3d;
import com.jaamsim.render.DisplayModelBinding;
import com.jaamsim.render.VisibilityInfo;
import com.jaamsim.ui.View;
import com.sandwell.JavaSimulation.DoubleListInput;
import com.sandwell.JavaSimulation.DoubleVector;
import com.sandwell.JavaSimulation.Entity;
import com.sandwell.JavaSimulation.EntityListInput;
import com.sandwell.JavaSimulation.Input;
import com.sandwell.JavaSimulation.Keyword;
import com.sandwell.JavaSimulation.ObjectType;
import com.sandwell.JavaSimulation.Vec3dInput;
import com.sandwell.JavaSimulation3D.DisplayEntity;

public abstract class DisplayModel extends Entity {
	public static final VisibilityInfo ALWAYS = new VisibilityInfo(null, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);

	private VisibilityInfo visInfo = ALWAYS;

	@Keyword(description = "The view objects this model will be visible on. If this is empty the entity is visible on all views.",
	         example = "ShipModel VisibleViews { TitleView DefaultView }")
	private final EntityListInput<View> visibleViews;

	@Keyword(description = "The distances from the camera that this display model will be visible",
	         example = "ShipModel DrawRange { 0 100 m }")
	private final DoubleListInput drawRange;

	@Keyword(description = "ModelScale scales the resulting visualization by this vector. Warning!! Resizing an entity with this set " +
	         "to a value that is not 1 is very unintuitive.",
	         example = "ShipModel ModelScale { 5 5 5 }")
	private final Vec3dInput modelScale;

	{
		visibleViews = new EntityListInput<View>(View.class, "VisibleViews", "Basic Graphics", null);
		this.addInput(visibleViews, true);

		DoubleVector defSize = new DoubleVector(2);
		defSize.add(0);
		defSize.add(Double.POSITIVE_INFINITY);
		drawRange = new DoubleListInput("DrawRange", "Basic Graphics", defSize);
		drawRange.setValidCount(2);
		drawRange.setValidRange(0, Double.POSITIVE_INFINITY);
		this.addInput(drawRange, true);

		modelScale = new Vec3dInput( "ModelScale", "Basic Graphics", new Vec3d(1, 1, 1));
		modelScale.setValidRange( 0.0001, 10000);
		this.addInput( modelScale, true);

	}

	public DisplayModel() {}

	public abstract DisplayModelBinding getBinding(Entity ent);

	public abstract boolean canDisplayEntity(Entity ent);

	public static DisplayModel getDefaultDisplayModelForClass(Class<? extends DisplayEntity> theClass) {
		for( ObjectType type : ObjectType.getAll() ) {
			if(type.getJavaClass() == theClass) {
				return type.getDefaultDisplayModel();
			}
		}
		return null;
	}

	@Override
	public void updateForInput( Input<?> in ) {
		super.updateForInput( in );

		if (in == visibleViews || in == drawRange) {
			double minDist = drawRange.getValue().get(0);
			double maxDist = drawRange.getValue().get(1);
			// It's possible for the distance to be behind the camera, yet have the object visible (distance is to center)
			// So instead use negative infinity in place of zero to never cull when close to the camera.
			if (minDist == 0.0) {
				minDist = Double.NEGATIVE_INFINITY;
			}
			visInfo = new VisibilityInfo(visibleViews.getValue(), minDist, maxDist);
		}

	}

	public VisibilityInfo getVisibilityInfo() {

		return visInfo;
	}

	public Vec3d getModelScale() {
		return modelScale.getValue();
	}
}

@@ -631,16 +631,57 @@
 odels;%0A%0A
+import com.jaamsim.input.ValueListInput;%0A
 import c
@@ -835,46 +835,33 @@
 com.
-sandwell.JavaSimulation.DoubleListInpu
+jaamsim.units.DistanceUni
 t;%0Ai
@@ -1874,21 +1874,20 @@
 e final 
-Doubl
+Valu
 eListInp
@@ -2187,16 +2187,162 @@
 Scale;%0A%0A
+%09private static final DoubleVector defRange = new DoubleVector(2);%0A%0A%09static %7B%0A%09%09defRange.add(0.0d);%0A%09%09defRange.add(Double.POSITIVE_INFINITY);%0A%09%7D%0A%0A
 %09%7B%0A%09%09vis
@@ -2474,113 +2474,8 @@
 );%0A%0A
-%09%09DoubleVector defSize = new DoubleVector(2);%0A%09%09defSize.add(0);%0A%09%09defSize.add(Double.POSITIVE_INFINITY);%0A
 %09%09dr
@@ -2488,21 +2488,20 @@
 e = new 
-Doubl
+Valu
 eListInp
@@ -2541,12 +2541,58 @@
  def
-Size
+Range);%0A%09%09drawRange.setUnitType(DistanceUnit.class
 );%0A%09

add units to the DisplayModel keywords DrawRange