#ifndef _HARMONY_CPP_
#define _HARMONY_CPP_

#include <iostream.h>
#include <stdlib.h>

#include <track.h>

#include "riemann.h"
#include "harmony.h"
#include "harmonyTrack.h"
#include "globals.h"


extern "C" {
  Track * riemann_track();
}



Harmony::Harmony() : _base_key(UNDEFKEY), _base_gen(UNDEFGEN), _key(UNDEFKEY), _genus(UNDEFGEN), _bass(0), _bass_abs(0), _ht((HarmonyTrack*) riemann_track()) {

}

Harmony::Harmony(Key basekey, Genus basegenus) : _base_key(basekey), _base_gen(basegenus), _key(UNDEFKEY), _genus(UNDEFGEN), _bass(0), _bass_abs(0),
						 _ht((HarmonyTrack*) riemann_track()) {

}

Harmony::Harmony(Key basekey, Genus basegenus, Chord c) : _base_key(basekey), _base_gen(basegenus), _key(UNDEFKEY), _genus(UNDEFGEN), _bass(0), _bass_abs(0),
							  _chord(c), _ht((HarmonyTrack*) riemann_track()) {
  analyse();
}

Harmony::Harmony(Harmony h, Chord c, int s) : _base_key(h.baseKey()), _base_gen(h.baseGenus()), _key(UNDEFKEY), _genus(UNDEFGEN), _bass(0), _bass_abs(s), _chord(c),
				       _ht((HarmonyTrack*) riemann_track()) {
  if (h.baseKey()==UNDEFKEY || h.baseGenus()==UNDEFGEN) {
    _base_key = _ht->key();
    _base_gen = _ht->genus();
  }
  analyse();
}



void Harmony::analyse() {
  // cout << endl << "ANALYSE: " << endl << sKey[_base_key] << " (" << sGenus[_base_gen] << ") " << sKey[_key] << " (" << sGenus[_genus] << ") : " << _chord;
  for (Key s=UNDEFKEY; s<KEY; ((int) s)++) {
    _maj[s] = 0;
    _min[s] = 0;
    _dim[s] = 0;
    for (Chord::Iterator ci = Chord::Iterator(_chord); !ci.done(); ci++) {

      _maj[s] += weight(s, MAJOR, ci.key(), ci.mult()) * harmonic_correlation(s, MAJOR, _base_key, _base_gen);
      _min[s] += weight(s, MINOR, ci.key(), ci.mult()) * harmonic_correlation(s, MINOR, _base_key, _base_gen);
      _dim[s] += weight(s, DIMINISHED, ci.key(), ci.mult());

    }
    
  }

  /* cout << "maj: "; for (Key k=GES; k<KEY; ((int)k)++) { cout << " " << sKey[k] << ": " << _maj[k] << " "; }; cout << endl;
     cout << "min: "; for (Key k=GES; k<KEY; ((int)k)++) { cout << " " << sKey[k] << ": " << _min[k] << " "; }; cout << endl;
     cout << "dim: "; for (Key k=GES; k<KEY; ((int)k)++) { cout << " " << sKey[k] << ": " << _dim[k] << " "; }; cout << endl;
     int compar(const int a, const int b) { return a-b; }
     typedef int (*CmpFunction)(const void *, const void *);
     CmpFunction cmp = (CmpFunction) &compar;
     qsort((void*)_maj[0], KEY, sizeof(int), cmp);
  */
  
  int max = 0;
  Key mykey = UNDEFKEY;
  Genus mygen = UNDEFGEN;

  for (Key k=GES; k<KEY; ((int)k)++) {
    if (max < _maj[k]) { max = _maj[k]; mykey = k; mygen = MAJOR; }
    if (max < _min[k]) { max = _min[k]; mykey = k; mygen = MINOR; }
    if (max < _dim[k]) { max = _dim[k]; mykey = k; mygen = DIMINISHED; }
  }
  _key   = mykey;
  _genus = mygen;
  _bass  = toneOfStep(mykey, _bass_abs);

  /*
  int count = 5;
  for (int i=max; count>0; i--) {
    for (Key k=GES; k<KEY; ((int)k)++) {
      if (_maj[k] == i) { cout << i << ": " << sKey[k] << " major" << endl; count--; }
      if (_min[k] == i) { cout << i << ": " << sKey[k] << " minor" << endl; count--; }
      if (_dim[k] == i) { cout << i << ": " << sKey[k] << " dim" << endl; count--; }
    }
    }*/
}


void Harmony::print() {
  cout << "base:  " << sKey[_base_key] << " (" << _base_key << ") " << sGenus[_base_gen] << " (" << _base_gen << ") " << endl;
  cout << "chord: " << sKey[_key] << " (" << _key << ") " << sGenus[_genus] << " (" << _genus << ") " << endl;
  // cout << "function: " << _rfunction << endl;
  cout << _chord << endl;
}

#endif
