package net.mkonrad.synes.ctrl;

import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseWheelEvent;
import java.io.IOException;

import javax.media.j3d.Node;
import javax.vecmath.Point3f;

import net.mkonrad.synes.data.AbstractGraph;
import net.mkonrad.synes.data.Beat;
import net.mkonrad.synes.data.BeatGraph;
import net.mkonrad.synes.data.Instrument;
import net.mkonrad.synes.data.Layer;
import net.mkonrad.synes.data.Modulator;
import net.mkonrad.synes.data.SynthGraph;
import net.mkonrad.synes.data.SynthInstrument;
import net.mkonrad.synes.data.SynthObj;
import net.mkonrad.synes.gui.SceneCore;
import net.mkonrad.synes.gui.elements.AbstractGraphLine;
import net.mkonrad.synes.gui.elements.instruments.InstrumentShape;
import net.mkonrad.synes.synth.SynthExt;
import net.mkonrad.synes.util.DbgTools;
import net.mkonrad.synes.util.ErrTools;

abstract public class AbstractLayerPickingCtrl extends AbstractPickableObj
{
  private static boolean _keyListenerAdded = false;
  
  public AbstractLayerPickingCtrl(CentralPickingCtrl pickCtrl)
  {
    super(pickCtrl);
    
    if (!_keyListenerAdded) //don't add the keylistener twice!
    {
      _coreCtrl.addKeyListener(
        new KeyAdapter()
        {
          public void keyPressed(KeyEvent e)
          {
            int keyCode = e.getKeyCode();
            
            if (keyCode == KeyEvent.VK_ESCAPE ||
                keyCode == KeyEvent.VK_ENTER)
            {
              _pickCtrl.getLayerPickingCtrl().cancelGraphCreation();
            }
            else if (keyCode >= KeyEvent.VK_1 && keyCode <= KeyEvent.VK_9
                && (_pickCtrl.getState() == CentralPickingCtrl.STATE_GRAPH_CREATE
                    || _pickCtrl.getState() == CentralPickingCtrl.STATE_READY))
            {
              instrumentSelect(keyCode - 0x31);
            }
          }
        }
      );
      
      _keyListenerAdded = true;
    }
  }

  protected void instrumentSelect(int index)
  {
    if (_coreCtrl.getCurrLayer().getType() == Layer.TYPE_SYNTH
        && _pickCtrl.getCurrGraph() != null && _pickCtrl.getCurrGraph().size() < 2)
      return;
    
    try
    {
      _pickCtrl.setCurrInstrument(SceneCore.getInstrCabinet().get(_coreCtrl.getCurrLayer().getType(), index));
      
      if (_pickCtrl.getState() == CentralPickingCtrl.STATE_GRAPH_CREATE)
      {
        _pickCtrl.getCurrGraphLine().changePointerInstrument(_pickCtrl.getCurrInstrument());
       
        if (_coreCtrl.getCurrLayer().getType() == Layer.TYPE_SYNTH)
        {
          ((SynthLayerPickingCtrl)_pickCtrl.getLayerPickingCtrl()).changeSynthObjInstr(_pickCtrl.getCurrGraphLine().getPointerObj());
        }
      }
      
      if (_coreCtrl.getHUD() != null)
        _coreCtrl.getHUD().updateInstrChoice(index);
      
      if (_pickCtrl.getCurrInstrument().needsKeyboard())
        _coreCtrl.getGround().showKeyboard();
      else
        _coreCtrl.getGround().hideKeyboard();
      
    } catch (IndexOutOfBoundsException e)
    { //do nothing of this instrument doesnt exist
    }
  }

  public boolean clicked(Node pickedObj, Point3f intercept, int mouseState)
  {
    if (_pickCtrl.getCurrGraphLine() == null)
    {
      createNewGraph(intercept);        
    }
    else
    {
      if (mouseState == CentralPickingCtrl.MOUSE_DBLCLICK)
      {
        cleanUp();
        finishGraph(intercept);
      } else
      {
        addObjectToGraph(intercept);
      }
    }
    
    return true;
  }

  public boolean dragged(Point3f intercept, int mouseState)
  {
    return true;
  }
  
  public boolean released(Point3f intercept, int mouseState)
  {
    return true;
  }
  
  abstract protected void createNewGraph(Point3f intercept);
  abstract protected void addObjectToGraph(Point3f intercept);
  abstract protected void finishGraph(Point3f intercept);
  abstract public void cancelGraphCreation();
  
  protected void startMouseOver(AbstractGraphLine graphLine, SynthObj pointerObj, Point3f intercept)
  {
    graphLine.initLine(intercept, pointerObj);
    
    _coreCtrl.getCanvas3D().addMouseWheelListener(_mouseWheelListener);
  }
  
  protected void stopMouseOver(Point3f intercept)
  {
    _pickCtrl.getCurrGraphLine().releaseMove(intercept);
    _pickCtrl.resetCurrValues();
    
    _coreCtrl.getCanvas3D().removeMouseWheelListener(_mouseWheelListener);
    //_coreCtrl.getGuiCtrl().getOrbitControl().setEnable(true);
  }
  
  protected void cleanUp()
  {
  }
}
