package net.mkonrad.synes.ctrl;

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

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.SynthObj;
import net.mkonrad.synes.gui.elements.AbstractGraphLine;
import net.mkonrad.synes.gui.elements.BeatGraphLine;
import net.mkonrad.synes.gui.elements.instruments.InstrumentShape;
import net.mkonrad.synes.util.DbgTools;
import net.mkonrad.synes.util.ErrTools;

public class SeqLayerPickingCtrl extends AbstractLayerPickingCtrl
{

  public SeqLayerPickingCtrl(CentralPickingCtrl pickCtrl)
  {
    super(pickCtrl);
  }

  protected void changeBeatDur(int byValue)
  {
    Beat currBeat = ((BeatGraph)_pickCtrl.getCurrGraphLine().getGraph()).getBeat(_pickCtrl.getCurrGraphLine().getGraph().size()-1);
    float newDur = currBeat.getDur() + (float)byValue * (1.0f/16.0f);
    
    if (newDur <= 0)
       return;
    
    currBeat.setDur(newDur);
    _pickCtrl.getCurrGraphLine().movedPointer(null);
  }
  
  public boolean moved(Node pickedObj, Point3f intercept, int mouseState)
  {
    if (_pickCtrl.getCurrGraphLine() != null)
    {
      _pickCtrl.getCurrGraphLine().movedPointer(intercept);
    }
    
    return true;
  }
  
  protected void createNewGraph(Point3f intercept)
  {
    DbgTools.print("Creating new BeatGraph");
    _pickCtrl.setState(CentralPickingCtrl.STATE_GRAPH_CREATE);
    
    Beat newBeat = createNewBeat(intercept);
    Beat pointerBeat = createNewBeat(intercept);
    
    BeatGraph beatGraph = new BeatGraph();
    _pickCtrl.setCurrGraphId(beatGraph.getId());
    beatGraph.add(newBeat);
    newBeat.setGraph(beatGraph);
    
    BeatGraphLine graphLine = _pickCtrl.createGraphLine(beatGraph);
    _coreCtrl.getCurrLayer().addGraph(beatGraph);
    beatGraph.setLayerLevel(_coreCtrl.getLayerSet().getCurrLayerLevel());
    
    startMouseOver(graphLine, pointerBeat, intercept);
    
    //Add elements to the SceneGraph:
    _pickCtrl.addNewGraphElementsToScene(newBeat.getInstrumentShape().getBG());
  }
  
  protected void addObjectToGraph(Point3f intercept)
  {
    DbgTools.print("Adding beat to BeatGraph");
    Beat newBeat = createNewBeat(intercept);
    
    connectBeats(newBeat);
    
    _pickCtrl.getCurrGraphLine().clicked(newBeat);
    _pickCtrl.addNewGraphElementsToScene(newBeat.getInstrumentShape().getBG());
  }
  
  protected Beat createNewBeat(Point3f intercept /* more things to come */)
  {
    //get selected instrument
    Instrument currInstr = _pickCtrl.getCurrInstrument();
    
    //create new beat
    float lastDur = 1.0f;
    if (_pickCtrl.getCurrGraph() != null)
    {
      lastDur = ((Beat)_pickCtrl.getCurrGraph().getLast()).getDur();
    }
    
    Beat newBeat = new Beat(currInstr, lastDur, 0.1f, 1.0f); //TODO: make amp dependent on how long you press the mousebutton
    
    //create shape according to the selected instrument and the beat's attributes
    newBeat.setInstrumentShape(currInstr.createInstrumentShape(newBeat, intercept));
    
    DbgTools.print("Created new beat#" + newBeat.getId());
    
    return newBeat;
  }
  
  protected void connectBeats(Beat newBeat)
  {
    BeatGraph beatGraph = (BeatGraph) _pickCtrl.getCurrGraph();
    beatGraph.add(newBeat);
    newBeat.setGraph(beatGraph);
    
    Beat prevBeat = beatGraph.getBeat(beatGraph.size() - 2);
    newBeat.setPrevBeat(prevBeat);
    prevBeat.setNextBeat(newBeat);
  }
  
  public void cancelGraphCreation()
  {
    AbstractGraphLine graphLine = _pickCtrl.getCurrGraphLine();
    
    if (graphLine == null)
      return;
      
    if (graphLine.getGraph().size() <= 1)
    {
      DbgTools.print("Canceling BeatGraph construction");
      
      graphLine.canceled();
      _pickCtrl.getCurrGraphLine().getBG().detach();
      _coreCtrl.getCurrLayer().removeGraph(_pickCtrl.getCurrGraphId());
      
      stopMouseOver(null);
    }
    else
    {
      graphLine.canceled();
      finishGraph(null);
    }
  }
  
  protected void finishGraph(Point3f intercept)
  {
    DbgTools.print("Finishing BeatGraph");
    
    BeatGraph beatGraph = (BeatGraph) _pickCtrl.getCurrGraphLine().getGraph();
    
    if (beatGraph.getState() == BeatGraph.STATE_OPENED)
    {
      beatGraph.getBeat(beatGraph.size() - 1).setDur(beatGraph.getBeat(beatGraph.size() - 2).getDur());
    }

    if (_coreCtrl.isOSCMode())
    {

      DbgTools.print("Sending OSC data");
      _coreCtrl.getSCLang().sendOSCDataOneByOne("/change",
          beatGraph.generateOSCData(_coreCtrl.getCurrLayer().getSCGroup().getNodeID()));
    }
    else // Dbg:
    {
      _pickCtrl.processOSCMsg(null);
    }

    try
    {
      synchronized (_pickCtrl.getNotifyObj())
      {
        _pickCtrl.getNotifyObj().wait(500);
      }
    } catch (InterruptedException e)
    {
      ErrTools.print(e);
    }
    
    stopMouseOver(intercept);
  }
}
