package cz.fidentis.analyst.scene;

import com.jogamp.opengl.GL2;
import cz.fidentis.analyst.mesh.core.MeshFacet;
import cz.fidentis.analyst.mesh.core.MeshModel;
import java.awt.Color;
import java.util.List;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3d;

/**
 * A drawable triangular mesh, i.e., a mesh model with drawing information like 
 * material, transparency, color, relative transformations in the scene etc. 
 * This class encapsulates rendering state and parameters,
 * 
 * @author Radek Oslejsek
 * @author Richard Pajersky
 */
public class DrawableMesh extends Drawable {
    
    private final MeshModel model;
    
    /**
     * Constructor. 
     * 
     * @param model Drawable mesh model
     * @throws IllegalArgumentException if the model is {@code null}
     */
    public DrawableMesh(MeshModel model) {
        if (model == null) {
            throw new IllegalArgumentException("model is null");
        }
        this.model = model;
    }
    
    /**
     * Constructor. 
     * 
     * @param facet Mesh facet
     * @throws IllegalArgumentException if the model is {@code null}
     */
    public DrawableMesh(MeshFacet facet) {
        if (facet == null) {
            throw new IllegalArgumentException("facet is null");
        }
        this.model = new MeshModel();
        this.model.addFacet(facet);
    }
    
    @Override
    protected void initRendering(GL2 gl) {
        super.initRendering(gl);
        
        // showBackface
        //float[] pos = {0f, 0f, -1f, 0f};
        //gl.glLightfv(GL2.GL_LIGHT1, GL2.GL_POSITION, pos, 0);
        //if (isShowBackface()) {
        //    gl.glLightfv(GL2.GL_LIGHT1, GL2.GL_DIFFUSE, Color.white.getComponents(null), 0);
        //} else {
        //    gl.glLightfv(GL2.GL_LIGHT1, GL2.GL_DIFFUSE, Color.black.getComponents(null), 0);
        //}
    
        // set color of highlights
        Color col = getHighlights();
        float[] highlights = {col.getRed(), col.getGreen(), col.getBlue(), 1};
        gl.glMaterialf(GL2.GL_FRONT_AND_BACK, GL2.GL_SHININESS, 50);  
        gl.glMaterialfv(GL2.GL_FRONT_AND_BACK, GL2.GL_SPECULAR, highlights, 0);
    }
    
    @Override
    protected void renderObject(GL2 gl) {
        for (MeshFacet facet: getFacets()) {
            gl.glBegin(GL2.GL_TRIANGLES); //vertices are rendered as triangles
        
            // get the normal and tex coords indicies for face i  
            for (int v = 0; v < facet.getCornerTable().getSize(); v++) {            
                // render the normals
                Vector3d norm = facet.getVertices().get(facet.getCornerTable().getRow(v).getVertexIndex()).getNormal(); 
                if(norm != null) {
                    gl.glNormal3d(norm.x, norm.y, norm.z);
                }
                // render the vertices
                Point3d vert = facet.getVertices().get(facet.getCornerTable().getRow(v).getVertexIndex()).getPosition();
                gl.glVertex3d(vert.x, vert.y, vert.z);
            }
        
            gl.glEnd();
        }
    }
    
    /**
     * Returns list of individual facets.
     * 
     * @return list of individual facets.
     */
    public List<MeshFacet> getFacets() {
        return model.getFacets();
    }
    
    /**
     * @return {@link MeshModel}
     */
    public MeshModel getModel() {
        return this.model;
    }

}
