package mygame;

import com.jme3.app.SimpleApplication;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.AnalogListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.renderer.queue.RenderQueue;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.shape.Box;
import com.jme3.scene.shape.Cylinder;

/**
 *
 * @author Rolf
 */
public class Cannon extends Node implements AnalogListener {

    Node nodeBarrel;
    protected float baseRotation, barrelRotation;

    public Cannon(SimpleApplication sa) {
        // Materials
        Material matBase = new Material(sa.getAssetManager(), "Common/MatDefs/Light/Lighting.j3md");
        matBase.setBoolean("UseMaterialColors", true);
        matBase.setColor("Ambient", new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
        matBase.setColor("Diffuse", ColorRGBA.White);
        matBase.setColor("Specular", ColorRGBA.Orange);
        matBase.setFloat("Shininess", 2f); // shininess from 1-128
        matBase.setTexture("DiffuseMap", sa.getAssetManager().loadTexture("Textures/texCannon.JPG"));
        //
        Material matBarrel = new Material(sa.getAssetManager(), "Common/MatDefs/Light/Lighting.j3md");
        matBarrel.setBoolean("UseMaterialColors", true);
        matBarrel.setColor("Ambient", ColorRGBA.Red);
        matBarrel.setColor("Diffuse", ColorRGBA.Green);
        matBarrel.setColor("Specular", ColorRGBA.Gray);
        matBarrel.setFloat("Shininess", 4f); // shininess from 1-128
        //
        // Geometry Base
        Box box = new Box(2f, 2f, 2f);
        Geometry geomBase = new Geometry("ground", box);
        geomBase.setMaterial(matBase);
        geomBase.setLocalTranslation(0, 1.0f, 0);
        geomBase.setShadowMode(RenderQueue.ShadowMode.CastAndReceive);
        //
        // geometry barrel
        Cylinder barrel = new Cylinder(32, 32, 0.8f, 4f, true);
        Geometry geomBarrel = new Geometry("ground", barrel);
        geomBarrel.setMaterial(matBarrel);
        geomBarrel.setLocalTranslation(0, 0, 2.0f);
        geomBarrel.setShadowMode(RenderQueue.ShadowMode.CastAndReceive);
        //
        // put it all together
        // THIS is the top level node
        // attach base
        this.attachChild(geomBase);
        // attach barrel
        nodeBarrel = new Node();
        nodeBarrel.setLocalTranslation(0, 2f, 0);
        nodeBarrel.attachChild(geomBarrel);
        this.attachChild(nodeBarrel);
        setRotation(-0.3f, -0.5f);
        //
        // init input        
        sa.getInputManager().addMapping("BASE_LEFT", new KeyTrigger(KeyInput.KEY_LEFT));
        sa.getInputManager().addMapping("BASE_RIGHT", new KeyTrigger(KeyInput.KEY_RIGHT));
        sa.getInputManager().addMapping("BARREL_UP", new KeyTrigger(KeyInput.KEY_UP));
        sa.getInputManager().addMapping("BARREL_DOWN", new KeyTrigger(KeyInput.KEY_DOWN));
        sa.getInputManager().addListener(this, new String[]{"BASE_LEFT", "BASE_RIGHT", "BARREL_UP", "BARREL_DOWN"});
    }

    // -------------------------------------------------------------------------
    public void setRotation(float base, float barrel) {
        barrel = (float) Math.max(Math.min(barrel, 0.0), -FastMath.PI / 2.0);
        baseRotation = base;
        barrelRotation = barrel;
        Quaternion qBase = new Quaternion();
        qBase.fromAngleAxis(base, Vector3f.UNIT_Y);
        this.setLocalRotation(qBase);
        Quaternion qBarrel = new Quaternion();
        qBarrel.fromAngleAxis(barrel, Vector3f.UNIT_X);
        nodeBarrel.setLocalRotation(qBarrel);
    }

    // -------------------------------------------------------------------------
    public void onAnalog(String name, float value, float tpf) {
        if (name.equals("BASE_LEFT")) {
            baseRotation -= tpf;
        }
        if (name.equals("BASE_RIGHT")) {
            baseRotation += tpf;
        }
        if (name.equals("BARREL_UP")) {
            barrelRotation -= tpf;
        }
        if (name.equals("BARREL_DOWN")) {
            barrelRotation += tpf;
        }
        setRotation(baseRotation, barrelRotation);
    }
}
