#ifndef _DUMP_CPP_
#define _DUMP_CPP_

#include <iostream.h>

#include <reference.h>
#include <table.h>
#include <event.h>
#include <part.h>
#include <track.h>
#include <song.h>
#include <str.h>
#include <iterator.h>
#include <selectionIterator.h>
#include <note.h>
#include <masterEvent.h>
#include <midiEvent.h>
#include <audioEvent.h>
#include <symbol.h>

#include "dump.h"

extern Table * selectioN;
extern Table * selectionMemory;

// #define DUMP_CONTEXT Addon::TREAT_SELECTION + Addon::TREAT_TRACK + Addon::TREAT_PART + Addon::TREAT_SONG
#define DUMP_CONTEXT Addon::TREAT_ALL

extern "C" {
  Addon * dump(Element * target) { return new Dump(target); }
  const char  * dump_name()     { return "dump"; }             // the name to be used to list this operation
  const char  * dump_category() { return "testing"; }          // the category to be listed
  int     dump_context() { return DUMP_CONTEXT; }              // the context
}

/** To initialize the addon, use the following parameters:
    1. char * name      - the name of the operation
    2. Element * target - the target (just use the parameter from the Operations contructor)
    3. bool undoable    - use TO_BE_UNDONE or !TO_BE_UNDONE, depending on whether the operation shall be undoable or not
    4. int context      - just use the above defined context here
*/

Dump::Dump(Element * target) : Addon("dump element", target, !TO_BE_UNDONE, DUMP_CONTEXT) { run(); }

Dump::~Dump() {

}

void display(Event * event) {
  Position start  = event->internalStart();
  int length = event->duration();
  if (event->isA()==NOTE)
    {
      Note * note = (Note*) event;
      cout << "Note: " << start << " (" << length << "): " << note->cPitch() << "vel: " << note->vel() << endl;
    }
  else if (event->isA()==MASTEREVENT)
    {
      MasterEvent * master = (MasterEvent*) event;
      cout << "MasterEvent: " << start << " (" << length << "): ";
      int tempo = master->tempo();
      if (tempo==0) cout << "meter: " << master->meter0() << "/" << master->meter1();
      else          cout << "tempo: " << tempo;
      cout << endl;
    }
  else if (event->isA()==MIDIEVENT)
    {
      MidiEvent * midi = (MidiEvent*) event;
      cout << "MidiEvent: " << start << " (" << length << "): " << "code: " << midi->code() << ", channel: " << midi->channel()
	   << ", value:" << midi->value1() << ", " << midi->value2() << endl;
    }
  else if (event->isA()==AUDIOEVENT)
    {
      AudioEvent * audio = (AudioEvent*) event;
      cout << "AudioEvent: " << start << " (" << length << "): " << audio->name() << ", " << audio->fileName() << endl;
    }
  else if (event->isA()==SYMBOL)
    {
      Symbol * symbol = (Symbol*) event;
      cout << "Symbol: " << start << " (" << length << "): " << symbol->symbol() << ", " << symbol->displacement() << ", "
	   << symbol->parameter() << ", " << symbol->text() << endl;
    }
  else cout << *event << endl;
}


/**
 ** implement your action on the selection here
 **/
void Dump::selection(Table * selection) {
  cout << "contents of the current selection:\n" << endl;
  for (SelectionIterator i = SelectionIterator(); !i.done(); i++) {
    Event * event = (Event*) *i;
    display(event);
  }
  cout << "--------\ncontents of the current memory:\n" << endl;
  for (SelectionIterator i = SelectionIterator(selectionMemory); !i.done(); i++) {
    Event * event = (Event*) *i;
    display(event);
  }
  cout << "---------------------------------------------\n" << endl;
}


/**
 ** implement your action on the part here
 **/
void Dump::part(Part * part) {
  cout << "contents of this part:\n" << endl;
  for (Iterator i = Iterator(part); !i.done(); i++) {
    Event * event = (Event*) *i;
    display(event);
  }
  cout << "---------------------------------------------\n" << endl;

}

/**
 ** implement your action on the track here
 **/
void Dump::track(Track * track) {
  cout << "contents of track: ";
  cout << track->name()->getValue() << ":\n" << endl;
  for (Iterator i = Iterator(track); !i.done(); i++) {
    Event * event = (Event*) *i;
    display(event);
  }
  cout << "---------------------------------------------\n" << endl;
}

/**
 ** implement your action on the song here
 **/
void Dump::song(Song * song) {
  cout << "contents of song ";
  cout << song->title() << ":\n" << endl;
  int sz = song->size();
  for (int i=0; i<sz; i++) {
    Track * tr = (Track*) song->get(i);
    cout << "Track: " << tr->name()->getValue() << endl;
  }

  cout << "---------------------------------------------\n" << endl;
}

void Dump::undo() {
}

void Dump::redo() {
}






#endif
