/* Copyright (c) 1997-2009
   Ewgenij Gawrilow, Michael Joswig (Technische Universitaet Darmstadt, Germany)
   http://www.polymake.de

   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 2, or (at your option) any
   later version: http://www.gnu.org/licenses/gpl.txt.

   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.
--------------------------------------------------------------------------------
   $Project: polymake $$Id: Utils.java 9931 2010-11-19 19:58:46Z gawrilow $
*/

package de.tuberlin.polymake.common.jreality;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.Set;

import de.jreality.math.Matrix;
import de.jreality.math.MatrixBuilder;
import de.jreality.scene.Appearance;
import de.jreality.scene.Geometry;
import de.jreality.scene.IndexedFaceSet;
import de.jreality.scene.SceneGraphComponent;
import de.jreality.scene.Transformation;
import de.jreality.scene.data.Attribute;
import de.jreality.scene.data.DataList;
import de.jreality.scene.data.DataListSet;
import de.jreality.scene.data.DoubleArrayArray;
import de.jreality.util.SceneGraphUtility;

public class Utils {

	public static void explodeGeometry(SceneGraphComponent geom, double scale) {
		int n_comp = geom.getChildComponentCount();
		if (!(n_comp == 0)) {

			SceneGraphComponent center = geom.getChildComponent(0);
			Geometry center_geom = center.getGeometry();
			if (center_geom instanceof de.jreality.scene.PointSet) {

				de.jreality.scene.PointSet pts = (de.jreality.scene.PointSet) center_geom;
				DoubleArrayArray coords = (DoubleArrayArray) pts
						.getVertexAttributes(Attribute.COORDINATES);

				double[] barycntr = barycenter(coords);

				for (int k = 1; k < n_comp; ++k) {

					SceneGraphComponent scene_c = geom.getChildComponent(k);
					Geometry scene_geom = scene_c.getGeometry();
					if (scene_geom instanceof de.jreality.scene.PointSet) {

						pts = (de.jreality.scene.PointSet) scene_geom;
						coords = (DoubleArrayArray) pts
								.getVertexAttributes(Attribute.COORDINATES);
						double[] cntr = barycenter(coords);
						Matrix m = MatrixBuilder.euclidean().translate(
								scale * (cntr[0] - barycntr[0]),
								scale * (cntr[1] - barycntr[1]),
								scale * (cntr[2] - barycntr[2])).getMatrix();

						double[] mat = m.getArray();
						Transformation trans = new Transformation(mat);
						scene_c.setTransformation(trans);

					}
				}
			}
		}

	}

	public static void clearAttributes(SceneGraphComponent sgc) {
		de.jreality.scene.Geometry geom = sgc.getGeometry();
		if(geom != null) {
			for(String cat : geom.getGeometryAttributeCathegories()) {
				DataListSet attMap = geom.getAttributes(cat);
				for(Attribute att : new LinkedList<Attribute>(attMap.storedAttributes())) {
					if(att.equals(Attribute.COLORS)) { 
					   //maybe clear RELATIVE_RADII
						geom.setAttributes(cat,att,null);
					}
				}
			}
		}
		for(SceneGraphComponent child : sgc.getChildComponents()) {
			clearAttributes(child);
		}
	}
	
	public static void clearAppearance(SceneGraphComponent sgc) {
		sgc.setAppearance(null);
		for(SceneGraphComponent child : sgc.getChildComponents()) {
			clearAppearance(child);
		}
	}
	public void setTransparency(SceneGraphComponent geom, String name, double val) {	
		
		SceneGraphComponent g = null;
		int k = geom.getChildComponentCount();
		
		for(int j = 0; j < k ; ++j) {
			SceneGraphComponent sgc = geom.getChildComponent(j);
			if(sgc.getName() == name) {
				g = sgc;
				break;
			}
		}
			
		if(g!=null) {
			Appearance app = g.getAppearance();
			if(app == null)
				app = new Appearance();
			app.setAttribute("polygonShader.transparency", val);
			//System.err.println("POLYMAKE: Setting transparency:" + val);
			g.setAppearance(app);
			geom.setAppearance(app);
		} else {
			//System.err.println("POLYMAKE: geometry " + name + " does not exist!");
		}
		
	}

	private static double[] barycenter(DoubleArrayArray coordinates) {
		double[] result = { 0, 0, 0 };
		int length = coordinates.getLength();

		for (int k = 0; k < length; ++k) {
			result[0] += coordinates.getValueAt(k, 0);
			result[1] += coordinates.getValueAt(k, 1);
			result[2] += coordinates.getValueAt(k, 2);
		}

		result[0] /= length;
		result[1] /= length;
		result[2] /= length;

		return result;

	}

	/**
	 * @param i_sgc
	 * @return
	 */
	public static SceneGraphComponent copy(SceneGraphComponent i_sgc) {
		SceneGraphComponent sgc = new SceneGraphComponent();
		sgc.setAppearance((Appearance)SceneGraphUtility.copy(i_sgc.getAppearance()));
		sgc.setGeometry(new IndexedFaceSet());
		Set cathegories = sgc.getGeometry().getGeometryAttributeCathegories();
		for (Iterator ci = cathegories.iterator(); ci.hasNext();) {
			String cathegory = (String) ci.next();
			DataListSet dls = i_sgc.getGeometry().getAttributes(cathegory);
			for (Iterator ai = dls.storedAttributes().iterator(); ai.hasNext();) {
				Attribute attr = (Attribute) ai.next();
				Object dl = new Object();
				dls.getList(attr).copyTo(dls.getList(attr).getStorageModel(),dl);
				System.out.println(dls.getList(attr).toString());
				sgc.getGeometry().setAttributes(cathegory, attr,(DataList)dl);	
			}
			System.out.println(dls);
			
		}
		return sgc;
	}

	
}
