
/*
 * Copyright (C) 2002 - 2007 Lehrstuhl Grafische Systeme, BTU Cottbus
 *
 * 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 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

package de.grogra.c4d;

import javax.vecmath.*;
import de.grogra.c4d.model.C4D;

public class BaseObject
{
	private final BaseDocument document;
	private final long documentPointer;
	private final long handle;

	public BaseObject(BaseDocument scene, long handle)
	{
		if (handle == 0)
		{
			throw new NullPointerException();
		}
		this.document = scene;
		documentPointer = scene.getPointer();
		this.handle = handle;
	}

	BaseObject(int type, boolean addPhongTag, BaseDocument documentForXLObject, boolean setNameIfNew)
	{
		document = (documentForXLObject != null) ? documentForXLObject : C4D.getCurrentDocument();
		if (document == null)
		{
			throw new IllegalStateException("No current scene");
		}
		documentPointer = document.getPointer();
		long h = (documentForXLObject != null) ? documentForXLObject.getHandleForXLObject() : 0;
		handle = (h != 0) ? h : C4D.newBaseObject(documentPointer, type, addPhongTag);
		if (handle == 0)
		{
			throw new IllegalArgumentException("Invalid type " + type);
		}
		boolean existed = document.registerObject(handle, this);
		assert !existed || (h != 0);
		if (setNameIfNew && (h == 0))
		{
			setName(getClass().getSimpleName() + ' ' + Long.toHexString(handle));
		}
	}

	public BaseObject(int type, boolean addPhongTag)
	{
		this(type, addPhongTag, null, false);
	}

	public BaseObject(int type)
	{
		this(type, false, null, false);
	}

	public final BaseDocument getDocument()
	{
		return document;
	}

	public final long getDocumentPointer()
	{
		return documentPointer;
	}

	public final long getHandle()
	{
		return handle;
	}

	public String getName()
	{
		return C4D.getName(documentPointer, handle);
	}

	public void setName(String name)
	{
		C4D.setName(documentPointer, handle, name);
	}

	public BaseObject getNext()
	{
		return document.getBaseObject(C4D.getNext(documentPointer, handle));
	}

	public BaseObject getPred()
	{
		return document.getBaseObject(C4D.getPred(documentPointer, handle));
	}

	public BaseObject getUp()
	{
		return document.getBaseObject(C4D.getUp(documentPointer, handle));
	}

	public BaseObject getDown()
	{
		return document.getBaseObject(C4D.getDown(documentPointer, handle));
	}

	public BaseObject getDownLast()
	{
		return document.getBaseObject(C4D.getDownLast(documentPointer, handle));
	}

	public void insertUnder(BaseObject parent)
	{
		C4D.insertUnder(documentPointer, handle, parent.handle);
	}

	public void insertUnderLast(BaseObject parent)
	{
		C4D.insertUnderLast(documentPointer, handle, parent.handle);
	}

	public void removeChildren()
	{
		C4D.removeChildren(documentPointer, handle);
	}

	public int getType()
	{
		return C4D.getType(documentPointer, handle);
	}

	public boolean getBoolean(int id)
	{
		return C4D.getBoolean(documentPointer, handle, id);
	}

	public int getInt(int id)
	{
		return C4D.getInt(documentPointer, handle, id);
	}

	public double getReal(int id)
	{
		return C4D.getReal(documentPointer, handle, id);
	}

	public Vector3d getVector(int id)
	{
		Vector3d v = new Vector3d();
		C4D.getVector(documentPointer, handle, id, v);
		return v;
	}

	public Matrix4d getMatrix(int id)
	{
		Matrix4d m = new Matrix4d();
		C4D.getMatrix(documentPointer, handle, id, m);
		m.m33 = 1;
		return m;
	}

	public String getString(int id)
	{
		return C4D.getString(documentPointer, handle, id);
	}

	public BaseObject getObject(int id)
	{
		return document.getBaseObject(C4D.getLink(documentPointer, handle, id));
	}

	public void setBoolean(int id, boolean v)
	{
		C4D.setBoolean(documentPointer, handle, id, v);
	}

	public void setInt(int id, int v)
	{
		C4D.setInt(documentPointer, handle, id, v);
	}

	public void setReal(int id, double v)
	{
		C4D.setReal(documentPointer, handle, id, v);
	}

	public void setVector(int id, Tuple3d v)
	{
		C4D.setVector(documentPointer, handle, id, v.x, v.y, v.z);
	}

	public void setVector(int id, double vx, double vy, double vz)
	{
		C4D.setVector(documentPointer, handle, id, vx, vy, vz);
	}

	public void setMatrix(int id, Matrix4d v)
	{
		C4D.setMatrix(documentPointer, handle, id, v.m00, v.m01, v.m02, v.m03, v.m10, v.m11, v.m12, v.m13, v.m20, v.m21, v.m22, v.m23);
	}

	public void setString(int id, String v)
	{
		C4D.setString(documentPointer, handle, id, v);
	}

	public void setObject(int id, BaseObject o)
	{
		C4D.setLink(documentPointer, handle, id, (o != null) ? o.handle : 0);
	}


	public boolean getUserBoolean(int id)
	{
		return C4D.getUserInt(documentPointer, handle, id) != 0;
	}

	public int getUserInt(int id)
	{
		return C4D.getUserInt(documentPointer, handle, id);
	}

	public double getUserReal(int id)
	{
		return C4D.getUserReal(documentPointer, handle, id);
	}

	public Vector3d getUserVector(int id)
	{
		Vector3d v = new Vector3d();
		C4D.getUserVector(documentPointer, handle, id, v);
		return v;
	}

	public Matrix4d getUserMatrix(int id)
	{
		Matrix4d m = new Matrix4d();
		C4D.getUserMatrix(documentPointer, handle, id, m);
		m.m33 = 1;
		return m;
	}

	public String getUserString(int id)
	{
		return C4D.getUserString(documentPointer, handle, id);
	}

	public void setUserBoolean(int id, boolean v)
	{
		C4D.setUserInt(documentPointer, handle, id, v ? 1 : 0);
	}

	public void setUserInt(int id, int v)
	{
		C4D.setUserInt(documentPointer, handle, id, v);
	}

	public void setUserReal(int id, double v)
	{
		C4D.setUserReal(documentPointer, handle, id, v);
	}

	public void setUserVector(int id, Tuple3d v)
	{
		C4D.setUserVector(documentPointer, handle, id, v.x, v.y, v.z);
	}

	public void setUserVector(int id, double vx, double vy, double vz)
	{
		C4D.setUserVector(documentPointer, handle, id, vx, vy, vz);
	}

	public void setUserMatrix(int id, Matrix4d v)
	{
		C4D.setUserMatrix(documentPointer, handle, id, v.m00, v.m01, v.m02, v.m03, v.m10, v.m11, v.m12, v.m13, v.m20, v.m21, v.m22, v.m23);
	}

	public void setUserString(int id, String v)
	{
		C4D.setUserString(documentPointer, handle, id, v);
	}

	public void setPosition(Tuple3d v)
	{
		C4D.setPosition(documentPointer, handle, v.x, v.y, v.z);
	}

	public void setPosition(double x, double y, double z)
	{
		C4D.setPosition(documentPointer, handle, x, y, z);
	}

	public Vector3d getPosition()
	{
		Vector3d v = new Vector3d();
		C4D.getPosition(documentPointer, handle, v);
		return v;
	}

	public void setFrozenPosition(Tuple3d v)
	{
		C4D.setFrozenPosition(documentPointer, handle, v.x, v.y, v.z);
	}

	public void setFrozenPosition(double x, double y, double z)
	{
		C4D.setFrozenPosition(documentPointer, handle, x, y, z);
	}

	public Vector3d getFrozenPosition()
	{
		Vector3d v = new Vector3d();
		C4D.getFrozenPosition(documentPointer, handle, v);
		return v;
	}

	public void setRotation(Tuple3d v)
	{
		C4D.setRotation(documentPointer, handle, v.x, v.y, v.z);
	}

	public void setRotation(double x, double y, double z)
	{
		C4D.setRotation(documentPointer, handle, x, y, z);
	}

	public Vector3d getRotation()
	{
		Vector3d v = new Vector3d();
		C4D.getRotation(documentPointer, handle, v);
		return v;
	}

	public void setFrozenRotation(Tuple3d v)
	{
		C4D.setFrozenRotation(documentPointer, handle, v.x, v.y, v.z);
	}

	public void setFrozenRotation(double x, double y, double z)
	{
		C4D.setFrozenRotation(documentPointer, handle, x, y, z);
	}

	public Vector3d getFrozenRotation()
	{
		Vector3d v = new Vector3d();
		C4D.getFrozenRotation(documentPointer, handle, v);
		return v;
	}

	public void setScale(Tuple3d v)
	{
		C4D.setScale(documentPointer, handle, v.x, v.y, v.z);
	}

	public void setScale(double x, double y, double z)
	{
		C4D.setScale(documentPointer, handle, x, y, z);
	}

	public Vector3d getScale()
	{
		Vector3d v = new Vector3d();
		C4D.getScale(documentPointer, handle, v);
		return v;
	}

	public void setFrozenScale(Tuple3d v)
	{
		C4D.setFrozenScale(documentPointer, handle, v.x, v.y, v.z);
	}

	public void setFrozenScale(double x, double y, double z)
	{
		C4D.setFrozenScale(documentPointer, handle, x, y, z);
	}

	public Vector3d getFrozenScale()
	{
		Vector3d v = new Vector3d();
		C4D.getFrozenScale(documentPointer, handle, v);
		return v;
	}

	public void setMl(Matrix4d v)
	{
		C4D.setMl(documentPointer, handle, v.m00, v.m01, v.m02, v.m03, v.m10, v.m11, v.m12, v.m13, v.m20, v.m21, v.m22, v.m23);
	}

	public Matrix4d getMl()
	{
		Matrix4d v = new Matrix4d();
		C4D.getMl(documentPointer, handle, v);
		return v;
	}

	public void setMg(Matrix4d v)
	{
		C4D.setMg(documentPointer, handle, v.m00, v.m01, v.m02, v.m03, v.m10, v.m11, v.m12, v.m13, v.m20, v.m21, v.m22, v.m23);
	}

	public Matrix4d getMg()
	{
		Matrix4d v = new Matrix4d();
		C4D.getMg(documentPointer, handle, v);
		return v;
	}

	public Vector3d getPg()
	{
		Matrix4d m = new Matrix4d();
		C4D.getMg(documentPointer, handle, m);
		Vector3d v = new Vector3d();
		m.get(v);
		return v;
	}

	public Matrix4d getUpMg()
	{
		Matrix4d v = new Matrix4d();
		C4D.getUpMg(documentPointer, handle, v);
		return v;
	}

	public int getEditorMode()
	{
		return C4D.getEditorMode(documentPointer, handle);
	}

	public void setEditorMode(int mode)
	{
		C4D.setEditorMode(documentPointer, handle, mode);
	}

	public int getRenderMode()
	{
		return C4D.getRenderMode(documentPointer, handle);
	}

	public void setRenderMode(int mode)
	{
		C4D.setRenderMode(documentPointer, handle, mode);
	}

	public void setColorProperties(int mode, double r, double g, double b, boolean xray)
	{
		C4D.setColorProperties(documentPointer, handle, mode, r, g, b, xray);
	}

	public void setColorProperties(int mode, Tuple3d color, boolean xray)
	{
		C4D.setColorProperties(documentPointer, handle, mode, color.x, color.y, color.z, xray);
	}

	public void setColor(double r, double g, double b)
	{
		C4D.setColorProperties(documentPointer, handle, Constants.ID_BASEOBJECT_USECOLOR_AUTOMATIC, r, g, b, false);
	}

	public void setColor(Tuple3d color)
	{
		C4D.setColorProperties(documentPointer, handle, Constants.ID_BASEOBJECT_USECOLOR_AUTOMATIC, color.x, color.y, color.z, false);
	}

	public void setMaterial(String material)
	{
		C4D.setMaterial(documentPointer, handle, material);
	}

	public String toString()
	{
		return getClass().getName() + '@' + Long.toHexString(handle) + '[' + paramString() + ']';
	}
	
	protected String paramString()
	{
		return "type=" + getType();
	}

	public void select(int mode)
	{
		C4D.setSelection(documentPointer, handle, mode);
	}

	public double getTime()
	{
		return document.getTime();
	}

	public int getFps()
	{
		return document.getFps();
	}

	public double getFrameStep()
	{
		return document.getFrameStep();
	}

	public void setPoints(Tuple3d[] points)
	{
		C4D.setPoints(documentPointer, handle, points);
	}

	public BaseObject searchReferenceObject(String name)
	{
		return document.searchReferenceObject(name);
	}

	public BaseObject searchObject(String name)
	{
		return document.searchObject(name);
	}
}
