package net.mkonrad.synes.gui.elements;

import javax.media.j3d.Appearance;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.LineArray;
import javax.media.j3d.LineStripArray;
import javax.media.j3d.Material;
import javax.media.j3d.PolygonAttributes;
import javax.media.j3d.QuadArray;
import javax.media.j3d.Shape3D;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.media.j3d.TransparencyAttributes;
import javax.vecmath.Color3f;
import javax.vecmath.Point3f;
import javax.vecmath.TexCoord2f;
import javax.vecmath.Vector3f;

import com.sun.j3d.utils.picking.PickTool;

import net.mkonrad.synes.gui.SceneCore;
import net.mkonrad.synes.gui.style.Colors;
import net.mkonrad.synes.util.DbgTools;

/**
 * Ground shape is a rectangular plane that is alsways at the current layer level
 * to provide a shape to pick at.
 * 
 * @author mako
 *
 */
public class GroundShape extends Shape3D
{
  public final static float GROUND_SIZE_X = 10.0f;
  public final static float GROUND_SIZE_Y = 6.0f;
  
  private BranchGroup _bg;
  private TransformGroup _tg;
  
  private Keyboard _keyboard;
  
  private boolean _isHidden = true;
  
  public GroundShape()
  {
    _bg = new BranchGroup();
    _bg.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND);
    _bg.setCapability(BranchGroup.ALLOW_CHILDREN_WRITE);
    _bg.setCapability(TransformGroup.ENABLE_PICK_REPORTING);
    
    _tg = new TransformGroup();
    _tg.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
    _tg.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND);
    _tg.setCapability(BranchGroup.ALLOW_CHILDREN_WRITE);
    _tg.setCapability(TransformGroup.ENABLE_PICK_REPORTING);
    
    this.setCapability(ALLOW_PICKABLE_WRITE);
    this.setCapability(ENABLE_PICK_REPORTING);
    this.setPickable(true);
    PickTool.setCapabilities(this, PickTool.INTERSECT_FULL);
    
    createGeometry();
    createAppearance();
    
    _keyboard = new Keyboard();
    
    _tg.addChild(this);
    _bg.addChild(_tg);
  }
  
  public BranchGroup getBG()
  {
    return _bg;
  }
  
  public void showKeyboard()
  {
    if (_isHidden)
    {
      _tg.addChild(_keyboard.getBG());
      _isHidden = false;
    }
  }
  
  public void hideKeyboard()
  {
    if (!_isHidden)
    {
      _tg.removeChild(_keyboard.getBG());
      _isHidden = true;
    }
  }
  
  public void setAtHeight(float h)
  {
    //DbgTools.print("Ground is now at height: " + h);
    setPos(new Vector3f(0f, 0f, h));
  }
  
  public void setPos(Vector3f posVec)
  {
    Transform3D t3d = new Transform3D();
    t3d.setTranslation(posVec);
    _tg.setTransform(t3d);
  }
  
  private void createGeometry()
  { 
    float sX = GROUND_SIZE_X / 2.0f;
    float sY = GROUND_SIZE_Y / 2.0f;
    
    /*
     * create borders around the ground plane
     */
    int numLinePoints = 5;  //because we use a line *strip*
    
    Shape3D lines = new Shape3D();
    lines.setPickable(false);
    
    LineStripArray linesGeom = new LineStripArray(numLinePoints, 
        LineStripArray.COORDINATES | LineStripArray.COLOR_3, new int[] {numLinePoints} );
    
    //set coords
    Point3f[] linePoints = {
        new Point3f(-sX, -sY, 0),
        new Point3f(-sX, sY, 0),
        new Point3f(sX, sY, 0),
        new Point3f(sX, -sY, 0),
        new Point3f(-sX, -sY, 0)
    };
    
    linesGeom.setCoordinates(0, linePoints);
    
    //set color
    Color3f lineColors[] = new Color3f[numLinePoints];
    for (int i = 0; i < lineColors.length; i++)
    {
      lineColors[i] = Colors.groundBorders;
    }
    
    linesGeom.setColors(0, lineColors);
    
    //set geometry
    linesGeom.setCapability(LineStripArray.ALLOW_COORDINATE_READ);
    linesGeom.setCapability(LineStripArray.ALLOW_COUNT_READ);
    lines.setGeometry(linesGeom);
    
    //attach to TG
    _tg.addChild(lines);
    
    /*
     * create ground shape
     */
    QuadArray plane = new QuadArray(4,
        QuadArray.COORDINATES | QuadArray.NORMALS);
    
    //set coords
    Point3f[] cornerPoints = {
        new Point3f(-sX, -sY, 0),
        new Point3f(-sX, sY, 0),
        new Point3f(sX, sY, 0),
        new Point3f(sX, -sY, 0)
    };

    plane.setCoordinates(0, cornerPoints);
    
    plane.setCapability(QuadArray.ALLOW_COORDINATE_READ);
    plane.setCapability(QuadArray.ALLOW_COUNT_READ);
    plane.setCapability(QuadArray.ALLOW_FORMAT_READ);
    plane.setCapability(QuadArray.ALLOW_VERTEX_ATTR_READ);
    
    //set geometry
    this.setGeometry(plane);
  }
  
  private void createAppearance()
  {
    Appearance app = new Appearance();
    
    //disable backface-culling
    PolygonAttributes pa = new PolygonAttributes();
    pa.setCullFace(PolygonAttributes.CULL_NONE);   
    app.setPolygonAttributes(pa);
    
    //set color
    Material mat = new Material();
    mat.setAmbientColor(Colors.ground);
    app.setMaterial(mat);
    
    //set transparency
    TransparencyAttributes trans = new TransparencyAttributes();
    trans.setTransparencyMode(TransparencyAttributes.BLENDED);
    trans.setTransparency(1.00f);
    app.setTransparencyAttributes(trans);
    
    //set appearance
    this.setAppearance(app);
  }
}
