package org.andresoviedo.app.model3D.services.collada.loader;

import android.opengl.Matrix;
import android.renderscript.Matrix4f;
import android.util.Log;

import org.andresoviedo.app.model3D.services.collada.entities.JointData;
import org.andresoviedo.app.model3D.services.collada.entities.SkeletonData;
import org.andresoviedo.app.util.xml.XmlNode;

import java.util.ArrayList;
import java.util.List;


public class SkeletonLoader2 {

	private XmlNode visualScene;

	private List<String> boneOrder = new ArrayList<String>();

	private int jointCount = 0;

	private static final float[] CORRECTION = new float[16];
	static{
		Matrix.setIdentityM(CORRECTION,0);
		Matrix.rotateM(CORRECTION,0,CORRECTION,0,-90, 1, 0, 0);
	}

	public SkeletonLoader2(XmlNode visualSceneNode) {
		this.visualScene = visualSceneNode.getChild("visual_scene");
	}
	
	public SkeletonData extractBoneData(){
		XmlNode node = visualScene.getChildWithAttribute("node","id","Armature");
		JointData headJoint = loadJointData(node, true);
		if (jointCount != boneOrder.size()) {
			Log.e("SkeletonLoader2", "jointCount != boneOrder: " + jointCount + " != " + boneOrder.size());
			jointCount = boneOrder.size();
		}
		return new SkeletonData(jointCount, headJoint);
	}
	
	private JointData loadJointData(XmlNode jointNode, boolean isRoot){
		JointData joint = extractMainJointData(jointNode, isRoot);
		for(XmlNode childNode : jointNode.getChildren("node")){
			joint.addChild(loadJointData(childNode, false));
		}
		return joint;
	}
	
	private JointData extractMainJointData(XmlNode jointNode, boolean isRoot){
		XmlNode instance_geometry = jointNode.getChild("instance_geometry");
		String meshId = instance_geometry != null? instance_geometry.getAttribute("url").substring(1) : null;
		String nameId = jointNode.getAttribute("id");
		int index = boneOrder.indexOf(nameId);
		if (index == -1){
			Log.e("SkeletonLoader2","Joint not found in order: "+nameId);
			boneOrder.add(nameId);
			index = boneOrder.indexOf(nameId);
		}
		String[] matrixData = jointNode.getChild("translate").getData().split(" ");
		float[] matrix = new float[16];
		Matrix.setIdentityM(matrix,0);
		Matrix.translateM(matrix,0,matrix,0,Float.valueOf(matrixData[0]),Float.valueOf(matrixData[1]),Float.valueOf(matrixData[2]));
		// Matrix.transposeM(matrix,0,matrix,0);
		if(isRoot){
			//because in Blender z is up, but in our game y is up.
			// Matrix.multiplyMM(matrix,0,CORRECTION,0,matrix,0);
		}
		jointCount++;
		return new JointData(index, nameId, matrix).setMeshId(meshId);
	}
	
	private float[] convertData(String[] rawData){
		float[] matrixData = new float[16];
		for(int i=0;i<matrixData.length;i++){
			matrixData[i] = Float.parseFloat(rawData[i]);
		}
		return matrixData;
	}
}