package net.mkonrad.synes.gui.elements;

import javax.media.j3d.Appearance;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.GeometryArray;
import javax.media.j3d.PolygonAttributes;
import javax.media.j3d.QuadArray;
import javax.media.j3d.Shape3D;
import javax.media.j3d.TransparencyAttributes;
import javax.vecmath.Color3f;
import javax.vecmath.Point3f;

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

/**
 * This class represents a MIDI-Keyboard. It can displayed above the ground
 * layer as a visual help. 
 * 
 * @author mako
 *
 */
public class Keyboard
{
  //private static int _octaves;
  
  private Color3f _colorWhite = Colors.white;
  private Color3f _colorBlack = Colors.black;
  
  private BranchGroup _bg;
  private Appearance _app;
  
  
  public Keyboard()
  {
    _bg = new BranchGroup();
    //_bg.setCapability(BranchGroup.ALLOW_PARENT_READ);
    _bg.setCapability(BranchGroup.ALLOW_DETACH);
    _bg.setPickable(false);
    
    createAppearance();
    createGeometry();
  }
  
  public BranchGroup getBG()
  {
    return _bg;
  }
  
  public float getKeyWidth()
  {
    return (float)(GroundShape.GROUND_SIZE_Y / (SceneCore.DEFAULT_NUM_OCTAVES * 12));
  }
  
  private void createGeometry()
  {
    int whitePointsSize = SceneCore.DEFAULT_NUM_OCTAVES * 7 * 4;  //7 white keys and 4 corner points
    int blackPointsSize = SceneCore.DEFAULT_NUM_OCTAVES * 5 * 4;  //5 black keys and 4 corner points
    
    Point3f[] whitePoints = new Point3f[whitePointsSize];
    Point3f[] blackPoints = new Point3f[blackPointsSize];
    Color3f[] whiteColors = new Color3f[whitePointsSize];
    Color3f[] blackColors = new Color3f[blackPointsSize];
    
    QuadArray whitePlanes = new QuadArray(whitePointsSize,
        GeometryArray.COORDINATES | GeometryArray.COLOR_3);
    whitePlanes.setCapability(QuadArray.ALLOW_COORDINATE_WRITE);
    QuadArray blackPlanes = new QuadArray(blackPointsSize,
        GeometryArray.COORDINATES | GeometryArray.COLOR_3);
    blackPlanes.setCapability(QuadArray.ALLOW_COORDINATE_WRITE);
    
    Shape3D whiteKeys = new Shape3D();
    Shape3D blackKeys = new Shape3D();
    
    whiteKeys.setPickable(false);
    blackKeys.setPickable(false);
    
    //GENERATE COORDS
    int wPntCounter = 0, bPntCounter = 0;
    float x = GroundShape.GROUND_SIZE_X / 2.0f;
    float y = -GroundShape.GROUND_SIZE_Y / 2.0f;
    float keyWidth = getKeyWidth();
    
    for (int oct = 0; oct < SceneCore.DEFAULT_NUM_OCTAVES; oct++)
    {
      boolean isWhite = true;
      for (int key = 0; key < 12; key++)
      {
        if (key != 0 && key != 5)
          isWhite = !isWhite;
        else
          isWhite = true; //change to white at E
                
        if (isWhite == true)
        {
          wPntCounter = createPoints(wPntCounter, whitePoints, whiteColors, _colorWhite, x, y, 0f, keyWidth);
        }
        else
        {
          bPntCounter = createPoints(bPntCounter, blackPoints, blackColors, _colorBlack, x, y, 0f, keyWidth);
        }
        
        y+=keyWidth;
      }
    }
    
    //SET COORDS
    whitePlanes.setCoordinates(0, whitePoints);
    blackPlanes.setCoordinates(0, blackPoints);
    
    //SET COLORS
    whitePlanes.setColors(0, whiteColors);
    blackPlanes.setColors(0, blackColors);
    
    //SET GEOMETRY
    whiteKeys.setGeometry(whitePlanes);
    blackKeys.setGeometry(blackPlanes);
    
    //SET APPEARANCE
    whiteKeys.setAppearance(_app);
    blackKeys.setAppearance(_app);
    
    //ADD TO SCENEGRAPH
    _bg.addChild(whiteKeys);
    _bg.addChild(blackKeys);
  }
  
  private int createPoints(int counter, Point3f[] array, Color3f[] colors, Color3f setColor, float x, float y, float z, float keyWidth)
  {
    array[counter*4] = new Point3f(-x, y, z);
    array[counter*4+1] = new Point3f(x, y, z);
    array[counter*4+2] = new Point3f(x, y+keyWidth, z);
    array[counter*4+3] = new Point3f(-x, y+keyWidth, z);
    
    for (int i = counter*4; i < counter*4 + 4; i++)
    {
      colors[i] = setColor;
    }
    
    return counter+1;
  }
  
  private void createAppearance()
  {
    _app = new Appearance();

    PolygonAttributes pa = new PolygonAttributes();
    pa.setCullFace(PolygonAttributes.CULL_NONE);   
    _app.setPolygonAttributes(pa);
    
    TransparencyAttributes trans = new TransparencyAttributes();
    trans.setTransparency(0.75f);
    trans.setTransparencyMode(TransparencyAttributes.BLENDED);
    trans.setCapability(TransparencyAttributes.ALLOW_VALUE_WRITE);
    
    _app.setTransparencyAttributes(trans);
  }
}
