/*
  melody-spanner.cc -- implement Melody_spanner

  source file of the GNU LilyPond music typesetter

  (c) 2005 Han-Wen Nienhuys <hanwen@xs4all.nl>

*/

#include "melody-spanner.hh"
#include "grob.hh"
#include "pointer-group-interface.hh"

/*
  TODO: this could be either item or spanner. For efficiency reasons,
  let's take item for now.
*/

		 
/*
  Interpolate stem directions for neutral stems.
 */
MAKE_SCHEME_CALLBACK(Melody_spanner,calc_neutral_stem_direction, 1);
SCM
Melody_spanner::calc_neutral_stem_direction (SCM smob)
{
  Grob *stem = unsmob_grob (smob);
  Grob *me =  unsmob_grob (stem->get_object ("melody-spanner"));
  if (!me || !me->is_live ())
    return SCM_UNSPECIFIED;
  
  extract_grob_set (me, "stems", stems);

  Array<Direction> dirs;
  for (int i = 0; i < stems.size (); i++)
    {
      dirs.push (to_dir (stems[i]->get_property ("default-direction")));
    }

  int last_nonneutral = -1;
  int next_nonneutral = 0;
  while (next_nonneutral < dirs.size() &&  !dirs[next_nonneutral])
    next_nonneutral ++;

  while (last_nonneutral < dirs.size () - 1) 
    {
      Direction d1 = CENTER;
      Direction d2 = CENTER;
      if (last_nonneutral >= 0)
	d1 = dirs[last_nonneutral];
      if (next_nonneutral < dirs.size ())
	d2 = dirs[next_nonneutral];

      Direction total = CENTER;
      if (d1 && d1 == d2)
	total = d1;
      else if (d1 && !d2)
	total = d1;
      else if (d2 && !d1)
	total = d2;
      else
	total = to_dir (me->get_property ("neutral-direction"));
      
      for (int i = last_nonneutral + 1; i <  next_nonneutral; i++)
	stems[i]->set_property ("neutral-direction", scm_from_int (total));


      last_nonneutral = next_nonneutral;
      while (last_nonneutral < dirs.size ()
	     && dirs[last_nonneutral])
	last_nonneutral ++;
      next_nonneutral = last_nonneutral;
      last_nonneutral --;

      while (next_nonneutral < dirs.size ()
	     && !dirs[next_nonneutral])
	next_nonneutral ++;
    }

  me->suicide ();
  return SCM_UNSPECIFIED;
}

void
Melody_spanner::add_stem (Grob *me, Grob *stem)
{
  Pointer_group_interface::add_grob (me, ly_symbol2scm ("stems"), stem);
  stem->set_object ("melody-spanner", me->self_scm ());
  stem->set_property ("neutral-direction", Melody_spanner::calc_neutral_stem_direction_proc);
}

ADD_INTERFACE (Melody_spanner, "melody-spanner-interface",
	       "Context dependent typesetting decisions.",

	       "stems "
	       "neutral-direction ");

  
