/*
 * Copyright (C) 2012 Darth Affe <http://wyrez.org> and contributors
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package org.wyrez.shootingstars.mesh;

import com.jme3.math.FastMath;
import com.jme3.math.Vector3f;
import com.jme3.scene.Mesh;
import com.jme3.scene.VertexBuffer;
import com.jme3.util.BufferUtils;

/**
 *
 * @author Darth Affe
 */
public class CinemaHex extends Mesh {
    /*    The vertices are located as following (continuing for the other side)
     * 
     *         12 18                15 21
     *           |\                  /| 
     *           | \                / |
     *           |  \              /  |
     *         0 \6  \____________/   / 3 9
     *            \13|19        14|20/
     *             \ |            | /
     *              \|____________|/
     *              1 7          2 8
     * 
     */

    private static final short[] GEOMETRY_INDICES_DATA = {
        12, 0, 7,/**/ 7, 19, 12,/**/ 13, 1, 8,/**/ 8, 20, 13,/**/ 14, 2, 9,/**/ 9, 21, 14,
        15, 3, 10,/**/ 10, 22, 15,/**/ 16, 4, 11,/**/ 11, 23, 16,/**/ 17, 5, 6,/**/ 6, 18, 17
    };
    private static final float[] GEOMETRY_NORMALS_DATA = {};
    private static final float[] GEOMETRY_TEXTURE_DATA = {
        0, 1,/**/ 0, 1,/**/ 0, 1,/**/ 0, 1,/**/ 0, 1,/**/ 0, 1,
        1, 1,/**/ 1, 1,/**/ 1, 1,/**/ 1, 1,/**/ 1, 1,/**/ 1, 1,
        0, 0,/**/ 0, 0,/**/ 0, 0,/**/ 0, 0,/**/ 0, 0,/**/ 0, 0,
        1, 0,/**/ 1, 0,/**/ 1, 0,/**/ 1, 0,/**/ 1, 0,/**/ 1, 0
    };
    private Vector3f center;
    private float width;
    private float radius;
    private float height;

    public CinemaHex(float width, float height) {
        this(Vector3f.ZERO, width, height);
    }

    public CinemaHex(Vector3f center, float width, float height) {
        super();
        updateGeometry(center, width, height);
    }

    /**
     * Empty constructor for serialization only. Do not use!
     */
    public CinemaHex() {
        super();
    }

    @Override
    public CinemaHex clone() {
        return new CinemaHex(center.clone(), width, height);
    }

    protected final void updateGeometry(Vector3f center, float width, float height) {
        this.center = center;
        this.width = width;
        this.radius = width * 2f / FastMath.sqrt(3f);
        this.height = height;
        updateGeometryIndices();
        updateGeometryNormals();
        updateGeometryTextures();
        updateGeometryVertices();
    }

    protected void updateGeometryIndices() {
        if (getBuffer(VertexBuffer.Type.Index) == null) {
            setBuffer(VertexBuffer.Type.Index, 3, BufferUtils.createShortBuffer(GEOMETRY_INDICES_DATA));
        }
    }

    protected void updateGeometryNormals() {
        if (getBuffer(VertexBuffer.Type.Normal) == null) {
            setBuffer(VertexBuffer.Type.Normal, 3, BufferUtils.createFloatBuffer(GEOMETRY_NORMALS_DATA));
        }
    }

    protected void updateGeometryTextures() {
        if (getBuffer(VertexBuffer.Type.TexCoord) == null) {
            setBuffer(VertexBuffer.Type.TexCoord, 2, BufferUtils.createFloatBuffer(GEOMETRY_TEXTURE_DATA));
        }
    }

    protected void updateGeometryVertices() {
        Vector3f[] vertices = computeVertices();
        setBuffer(VertexBuffer.Type.Position, 3, BufferUtils.createFloatBuffer(vertices));
        updateBound();
    }

    protected Vector3f[] computeVertices() {
        Vector3f[] vertices = new Vector3f[24];
        //bottom
        Vector3f verticesCenter = center;
        for (int i = 0; i < 6; i++) {
            vertices[i] = new Vector3f(verticesCenter.x + radius * FastMath.cos(i * FastMath.PI / 3f),
                    verticesCenter.y, (verticesCenter.z + radius * FastMath.sin(i * FastMath.PI / 3f)));
            vertices[i + 6] = vertices[i].clone();
        }
        //top
        verticesCenter = center.add(0f, height, 0f);
        for (int i = 0; i < 6; i++) {
            vertices[i + 12] = new Vector3f(verticesCenter.x + radius * FastMath.cos(i * FastMath.PI / 3f),
                    verticesCenter.y, (verticesCenter.z + radius * FastMath.sin(i * FastMath.PI / 3f)));
            vertices[i + 18] = vertices[i + 12].clone();
        }
        return vertices;
    }
}
