#ifndef _PARALLELS_CPP_
#define _PARALLELS_CPP_

#include <iostream.h>

#include <reference.h>
#include <table.h>
#include <event.h>
#include <part.h>
#include <track.h>
#include <scoreTrack.h>
#include <position.h>
#include <song.h>
#include <note.h>
#include <midiEvent.h>
#include <stdlib.h>
#include <songIterator.h>

#include "parallels.h"


#define PARALLELS_CONTEXT Addon::TREAT_SONG

extern "C" {
  Addon * parallels(Element * target) { return new Parallels(target); }
  const char  * parallels_name() { return "parallels"; }
  const char  * parallels_category() { return "harmony"; }
  int     parallels_context() { return PARALLELS_CONTEXT; }
}


Parallels::Parallels(Element * target) : Addon("find parallels", target, TO_BE_UNDONE, PARALLELS_CONTEXT) { run(); }

Parallels::~Parallels() {

}


int sgn(int i) {
  if (i==0) return 0;
  else if (i>0) return 1;
  else return -1;
}

void Parallels::song(Song * _song) {
  int ntracks = 0;
  ntracks = _song->size();

  _track = new ScoreTrack();
  _track->setName("* parallels...");
  _part = new Part(_track);
  _track->add(_part);
  _song->add(_track);
  long pp = 0;

  int maxvoices = ntracks*10;
  int pitches[maxvoices]; // in here we put the pitches to compare!
  int tendency[maxvoices]; // in here we put the tangent slope prev -> note
  int lengths[maxvoices];
  int count = 0;

  SongIterator * si = new SongIterator(_song, _song->left(), _song->right());

  Event * event = 0;
  Note * note   = 0;
  Track * tr    = 0;
  int temp = 0;
  Note * prevnote = 0;
  int pitchDiff = 0;
  int parallel = 0;

  while ( !si->done() ) {
    count = 0;
    for (int t=0; t<ntracks; t++) {
      tr = si->track(t);
      while (si->startsAt(t,pp)) {
	if (!si->mute(t)) {
	  event = (Event*) (*si)[t];
	  if (event->isA()==NOTE) {
	    note = (Note*) event;
	    // alsa->playNote(0, aiterator->channel(t), tr->pitch(note), tr->vel(note), pp + tr->delay(), note->duration());
	    if (count<maxvoices) {
	      prevnote = (Note*) tr->prev(note);
	      if (prevnote!=0) tendency[count] = note->pitch() - prevnote->pitch(); else tendency[count] = 0;
	      lengths[count] = note->duration();
	      pitches[count++] = note->pitch();
	    } else {
	      cout << "ERROR: too many voices!" << endl;
	    }
	  }
	}
	si->increment(t);
      }
    }

    for (int i=0;i<count;i++) { // check for parallels:
      for (int k=0;k<i;k++) {
	pitchDiff = abs(pitches[i] - pitches[k]);
	parallel = (tendency[i]==tendency[k]) ? 1 : ( sgn(tendency[i])==sgn(tendency[k]) ? 2 : 0 ); // 0: nothing, 1: parallel, 2: verdeckt parallel
	// if (pitches[i] == pitches[k]) cout << "primes at " << pp << endl;
	if (pitchDiff==7) {
	  if (parallel==1) add("qp",pp,pitches[i],pitches[k],lengths[i],lengths[k],parallel); // quint parallels
	  else if (parallel==2) add("vqp",pp,pitches[i],pitches[k],lengths[i],lengths[k],parallel); // verdeckte quint parallels
	}
	if (pitchDiff==12) {
	  if (parallel==1) add("op",pp,pitches[i],pitches[k],lengths[i],lengths[k],parallel); // octave parallels
	  else if (parallel==2) add("vop",pp,pitches[i],pitches[k],lengths[i],lengths[k],parallel); // verdeckte octave parallels
	}
      }
    }

    pp++;
  }

}

void Parallels::add(const char * text, long pos, int p1, int p2, int len1, int len2, int parallel) {
  _part->add(new Note(p1,87,len1,Position(pos),0,0,parallel-2));
  _part->add(new Note(p2,87,len2,Position(pos),0,0,parallel-2));
}


void Parallels::undo() {
}

void Parallels::redo() {
}






#endif
