package net.mkonrad.synes.ctrl;

import java.io.IOException;

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

import net.mkonrad.synes.data.Beat;
import net.mkonrad.synes.data.BeatGraph;
import net.mkonrad.synes.data.Modulator;
import net.mkonrad.synes.data.SeqInstrument;
import net.mkonrad.synes.data.SynthObj;
import net.mkonrad.synes.gui.elements.BeatGraphLine;
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;

public class BeatPickingCtrl extends AbstractPickableObj
{
  SynthExt _playingSynthExt = null;
  
  public BeatPickingCtrl(CentralPickingCtrl pickCtrl)
  {
    super(pickCtrl);
  }

  public boolean clicked(Node pickedObj, Point3f intercept, int mouseState)
  {
    Beat beat = (Beat)pickedObj.getUserData();
    
    if (_pickCtrl.getState() == CentralPickingCtrl.STATE_GRAPH_CREATE)
    {
      return handleBeatGraphCreation(beat, intercept);
    }
    else if (_pickCtrl.getMouseEvent().isControlDown())
    {
      _pickCtrl.setState(CentralPickingCtrl.STATE_BEAT_IMPRO);
      //DbgTools.print("synthstart!!");
      //return true;
      return handleImprovBeatStart(beat, intercept);
    }
    else if (_pickCtrl.getState() == CentralPickingCtrl.STATE_READY)
    {
      _selectedSynthObj = (SynthObj)pickedObj.getUserData();
      _selectedGraphLine = _selectedSynthObj.getGraph().getGraphLine();
      
      startEditMode();
    }
    
    return true;
  }
  
  public boolean dragged(Point3f intercept, int mouseState)
  {
    if (_pickCtrl.getState() == CentralPickingCtrl.STATE_BEAT_IMPRO
        && _pickCtrl.getMouseEvent().isControlDown())
    {
      _pickCtrl.setState(CentralPickingCtrl.STATE_BEAT_IMPRO);
      return handleImprovBeatMod(intercept);
    }
    else if (_pickCtrl.getState() == CentralPickingCtrl.STATE_GRAPH_EDIT)
    {
      _selectedSynthObj.getInstrumentShape().setPos(intercept);
      _selectedGraphLine.movedObj(_selectedSynthObj);
    }
    
    return true;
  }
  
  public boolean moved(Node pickedObj, Point3f where, int mouseState)
  {
    return false;
  }
  
  public boolean released(Point3f intercept, int mouseState)
  {
    if (_pickCtrl.getState() == CentralPickingCtrl.STATE_BEAT_IMPRO)
    {
      handleImprovBeatStop();
      _pickCtrl.setState(CentralPickingCtrl.STATE_READY);
    }
    else if (_pickCtrl.getState() == CentralPickingCtrl.STATE_GRAPH_EDIT)
    { 
      if (_coreCtrl.isOSCMode())
      {
        _coreCtrl.getSCLang().sendOSCDataOneByOne("/change",
            ((Beat)_selectedSynthObj).generateOSCUpdate());
      }

      _selectedSynthObj = null;
      _selectedGraphLine = null;
      
      stopEditMode();
    }
    
    return true;
  }

  private boolean handleImprovBeatStart(Beat beat, Point3f intercept)
  {
    try
    {
      _pickCtrl.pauseBeatGraph((BeatGraph)beat.getGraph());
      _playingSynthExt = SynthExt.basicNew(_coreCtrl.getSCServer(), _coreCtrl.getSCStdGrp(), beat);
      _playingSynthExt.play(beat.getInstrument().getSynthArgs(), beat.getInstrument().getAllSynthValues(beat));
    } catch (IOException e)
    {
      ErrTools.print(e);
    }

    return true;
  }
  
  private boolean handleImprovBeatMod(Point3f intercept)
  {
    try
    {
      _playingSynthExt.modSeqSynth(intercept);
      //_playingSynthExt.set(_playingSynthExt.get.getInstrument().getSynthArgs(), new float[] { Beat.getAdjustedX(intercept.x), Beat.getAdjustedY(intercept.y) });
    } catch (IOException e)
    {
      ErrTools.print(e);
    }

    return true;
  }
  
  private boolean handleImprovBeatStop()
  {
    if (_playingSynthExt != null)
    {
      try
      {
        _playingSynthExt.release();
        _pickCtrl.resumeBeatGraph((BeatGraph)_playingSynthExt.getSynthObj().getGraph());
      } catch (IOException e)
      {
        ErrTools.print(e);
      }
      
      _playingSynthExt = null;
    }
    
    return true;
  }

  private boolean handleBeatGraphCreation(Beat beat, Point3f intercept)
  {
    BeatGraph beatGraph = (BeatGraph) _pickCtrl.getCurrGraphLine().getGraph();
    
    if (beat == beatGraph.get(0))
    {
      if (beatGraph.size() > 2)
      {
        ((BeatGraphLine)_pickCtrl.getCurrGraphLine()).closeBeatGraph();
        _pickCtrl.getLayerPickingCtrl().finishGraph(intercept);
        
        DbgTools.print("Closed beatgraph");
      }
    }
    else if (beat == beatGraph.get(beatGraph.size()-1))
    {
      _pickCtrl.getCurrGraphLine().cleanUpTail();
      _pickCtrl.getLayerPickingCtrl().finishGraph(intercept);
    }
    
    return true;
  }
}
