#ifndef _TEXSONG_C_
#define _TEXSONG_C_

#include "texSong.h"
#include "../kbPart.h"
#include "../kbNote.h"

#include "../qtScore.h"
#include "../qtScoreAddons.h"
#include "../qtKeyChooser.h"
#include "../kbPart.h"
#include "../kbNote.h"
#include "../kbLyrics.h"
#include "../kbTrack.h"
#include "../kbScoreTrack.h"
#include "../kbExp.h"
#include "../kbBow.h"
#include "../kbStem.h"
#include "../kbAuxElement.h"
#include <math.h>
#include <iostream.h>

extern int scrSigns[8];
extern int allSigns[15][7];
extern void createBreakGroups(ScoreGroup *& grp, ScoreGroup *& grp1, KbPosition pos, int length, KbPosition pOffset, KbPart * master, int met0, int met1);

extern int globalStaffCounter;


/**
 *  This writes a tex-file, to work with MusixTex
 */

TexSong::TexSong()
  : KbSongExtension("Tex Song")
{}

/**
 * This defines the algorithm that shall act on a song.
 */
void TexSong::act(KbTrack * track) {
  KbMain * main = track->gMain();
  master = main->Master();
  met0 = main->gMeter(0);
  met1 = main->gMeter(1);

  ScoreGroup * firstGroup = 0;
  // ScoreGroup * tmp = 0;

  KbPart * partList[128];
  KbPart * part;
  int scrKey = 0;
  int scrClef = 0;
  int parts = 0;
  int N = 0;
  int i = 0;
  for (KbTrack * tr=track; tr!=0; tr=tr->gNext()) {
    if ((tr->gPart()!=0) && (tr->gToggle(0)==FALSE) && (tr->isA()==0)) {
      partList[parts] = tr->gPart();
      parts++;
    }
  }

  KbScoreTrack * scTrack;
  ScoreBar * firstBar[parts];
  ScoreBar * myBar[parts];
  
  cout << "\\ifx\\documentclass\\undefined
\\documentstyle[twoside,11pt,musixdoc,multicol,backgrnd]{report}
\\else
\\documentclass[twoside,11pt]{report}
\\usepackage{multicol}
\\usepackage{musixdoc}
\\usepackage{backgrnd}
\\fi
\\def\\musictex{Music\\TeX{}}
\\startmuflex\\makeindex
\\begin{document}
\\begin{music}
\\parindent10mm
\\instrumentnumber{" << parts << "}
\\generalmeter{\\meterfrac{" << partList[0]->gTime1() << "}{" << partList[0]->gTime2() << "}}
\\generalsignature{" << partList[0]->gKey() << "}";


  for (N=0;N<parts;N++) {
    part = partList[parts-N-1];
    int pNum = N+1;

    scTrack = (KbScoreTrack*) part->gTrack();

    cout << "\n\\setname" << pNum << "{" << scTrack->gName() << "}
\\setstaffs" << pNum << "{1}";
  }
  

  cout << "\n\\startextract" << endl;
  
  /*
  KbPosition relPos = 0;
  KbPosition lpos = 0; //posLeft;
  for (N=0;N<parts;N++) {
    part = partList[parts-N-1];
    globalStaffCounter = parts-N-1;
    scrKey = part->gKey();
    scrClef = part->gClef();
    relPos = lpos - part->gOffset();

    for (i=0;i<7;i++) scrSigns[i]=allSigns[scrKey+7][i];
    
    ScoreGroup * myGroup = 0;
    // lpos = 0;
    KbAtom* atom = part->gFirstAtom();
    while (atom!=0) {
      if (atom->isNote()) {
	KbNote * note = (KbNote*) atom;
	if (myGroup == 0) {

	  myGroup = new NoteGroup(note,part->gOffset());
	  if (note->gPos()-relPos > 0) {
	    if (relPos.negative()>0)
	      createBreakGroups(firstGroup, tmp, lpos, note->gPos()+relPos.negative(), part->gOffset(), master, met0, met1);
	    else
	      createBreakGroups(firstGroup, tmp, lpos, note->gPos()-relPos.gPosTicks(), part->gOffset(), master, met0, met1);
	    tmp->sNext(myGroup);
	  } else {
	    firstGroup = myGroup;
	  }

	  / *
	  relPos = lpos - part->gOffset();
	  myGroup = new NoteGroup(note,part->gOffset());
	  if (note->gPos()-relPos > 0) {
	    createBreakGroups(firstGroup, tmp, relPos, note->gPos()-relPos.gPosTicks(), part->gOffset(), master, met0, met1);
	    tmp->sNext(myGroup);
	  } else {
	    firstGroup = myGroup;
	  }
	  * /
	} else {
	  myGroup = myGroup->append(note,part->gOffset(),master,met0,met1);
	}
      }
      
      
      atom = atom->gNext();

      / *      
      if (allParts==TRUE && atom==0 && part->gNext()!=0) { // to the following part ;-)
	part = part->gNext();
	atom = part->gFirstAtom();
	scrKey = part->gKey();
	clef = part->gClef();
      }
      * /
    }

    
    // now everything is packed up in groups, lets pack the
    // groups into parts:
    
    if (firstGroup) {
      firstBar[N] = new ScoreBar(firstGroup);
      ScoreBar * curBar = firstBar[N];
      for (myGroup = firstGroup->Next(); myGroup!=0; myGroup = myGroup->Next()) {
	curBar = curBar->append(myGroup,master,met0,met1);
      }
      if (curBar) curBar->fill(master,met0,met1);
     
    }
    
  } // loop N = 0 to parts
  */ 



    KbPosition relPos = 0;
    KbPosition lpos = 0; // posLeft;
    for (N=0;N<parts;N++) {
      part = partList[parts-N-1];
      globalStaffCounter = parts-N-1;
      
      for (i=0;i<7;i++) scrSigns[i]=allSigns[scrKey+7][i];
      
      ScoreGroup * myGroup = 0;
      ScoreGroup * tmp = 0;
      lpos = 0; //posLeft;
      relPos = lpos - part->gOffset();
      KbAtom* atom = part->gFirstAtom();
      while (atom!=0) {
	if (atom->isNote()) {
	  KbNote * note = (KbNote*) atom;
	  if (myGroup == 0) {
	    // cout << "soieses" << endl;
	    myGroup = new NoteGroup(note,part->gOffset());
	    if (note->gPos()-relPos > 0) {
	      if (relPos.negative()>0)
		createBreakGroups(firstGroup, tmp, lpos, note->gPos()+relPos.negative(), part->gOffset(), master, met0, met1);
	      else
		createBreakGroups(firstGroup, tmp, lpos, note->gPos()-relPos.gPosTicks(), part->gOffset(), master, met0, met1);
	      tmp->sNext(myGroup);
	    } else {
	      firstGroup = myGroup;
	    }
	  } else {
	    myGroup = myGroup->append(note,part->gOffset(),master,met0,met1);
	  }
	}
	
	atom = atom->gNext();
	
	/*if (allParts==TRUE && atom==0 && part->gNext()!=0) { // to the following part ;-)
	  part = part->gNext();
	  atom = part->gFirstAtom();
	  scrKey = part->gKey();
	  clef = part->gClef();
	  }*/
	
      }
      
      
      // now everything is packed up in groups, lets pack the
      // groups into bars:
      
      
      if (firstGroup) {
	firstBar[N] = new ScoreBar(firstGroup);
	ScoreBar * curBar = firstBar[N];
	for (myGroup = firstGroup->Next(); myGroup!=0; myGroup = myGroup->Next()) {
	  curBar = curBar->append(myGroup,master,met0,met1);
	}
	if (curBar) curBar->fill(master,met0,met1);
      }
      
    }



  
  /*
  for (int i=0;i<parts;i++) myBar[i] = firstBar[i];
  int loop = 1;
  int count = 0;
  while (loop) {
    cout << count++ << endl;
    for (int i=0;i<parts;i++) {
      cout << "Bar: " << count << ", Part: " << i+1 << " | " << myBar[i] << ", n: " << myBar[i]->Next() << endl;
    }
    for (int i=0;i<parts;i++) myBar[i] = myBar[i]->Next();
    for (int i=0;i<parts;i++) if (myBar[i]==0) loop = 0;
  }  
  */
  
  for (int i=0;i<parts;i++) myBar[i] = firstBar[i];
  int loop = 1;
  // int count = 0;
  while (loop) {
    // cout << count++ << endl;
    cout << "\\Notes";
    for (int i=0;i<parts;i++) {
      scrKey = partList[i]->gKey();
      for (int ii=0;ii<7;ii++) scrSigns[ii]=allSigns[scrKey+7][ii];
      if (i>0) cout << " | ";
      relPos = partList[i]->gOffset() - lpos;
      myBar[i]->tex(relPos,scrClef,master,met0,met1);
    }
    cout << "\\en" << endl << "\\bar" << endl;
    for (int i=0;i<parts;i++) myBar[i] = myBar[i]->Next();
    for (int i=0;i<parts;i++) if (myBar[i]==0) loop = 0;
  }

  /*
    ScoreGroup * tmp;
    KbPosition curPos;
    
    for (myGroup = firstGroup; myGroup!=0;) {
    // myGroup->print();
    oldTimeBar = curBar;
    relPos = part->gOffset() - lpos;
    curPos = myGroup->start() + relPos;
    curMet0 = met0; curMet1 = met1; curPos.gBBT(curBar,curBeat,curTick,master,curMet0,curMet1,true);
    if (oldTimeBar!=curBar) {
    for (i=0;i<7;i++) scrSigns[i]=allSigns[scrKey+7][i];
    //for (i=0;i<curBar-oldTimeBar;i++)
    //	cout << "\\bar" << endl;
    }
    myGroup->tex(relPos,pixPerTick,xoffset,yoffset,scrClef,master,met0,met1);
    tmp = myGroup->Next();
    delete myGroup;
    myGroup = tmp;
    }
  */
  // DOIT: remove bars and groups, etc !!!
  
  cout << "\\endextract
\\end{music}
\\endmuflex
\\end{document}" << endl;
  





  /*
  ScoreGroup * firstGroup = 0;
  ScoreGroup * tmp = 0;
  KbScoreTrack * scTrack;
  ScoreBar * firstBar;
  ScoreBar * myBar;
  
  cout << "\\ifx\\documentclass\\undefined
\\documentstyle[twoside,11pt,musixdoc,multicol,backgrnd]{report}
\\else
\\documentclass[twoside,11pt]{report}
\\usepackage{multicol}
\\usepackage{musixdoc}
\\usepackage{backgrnd}
\\fi
\\def\\musictex{Music\\TeX{}}
\\startmuflex\\makeindex
\\begin{document}
\\begin{music}
\\parindent10mm
\\instrumentnumber{1}
\\generalmeter{\\meterfrac{" << part->gTime1() << "}{" << part->gTime2() << "}}
\\generalsignature{" << part->gKey() << "}";


  scTrack = (KbScoreTrack*) part->gTrack();

  cout << "\\setname1{" << scTrack->gName() << "}
\\setstaffs1{1}";
  
  

  cout << "\\startpiece" << endl;
  
  KbPosition relPos = 0;
  KbPosition lpos = 0; //posLeft;

  int i=0;
  for (i=0;i<7;i++) scrSigns[i]=allSigns[part->gKey()+7][i];
    
  ScoreGroup * myGroup = 0;
  // lpos = 0;
  KbAtom* atom = part->gFirstAtom();
  while (atom!=0) {
    if (atom->isNote()) {
      KbNote * note = (KbNote*) atom;
      if (myGroup == 0) {
	relPos = lpos - part->gOffset();
	myGroup = new NoteGroup(note,part->gOffset());
	if (note->gPos()-relPos > 0) {
	  createBreakGroups(firstGroup, tmp, relPos, note->gPos()-relPos.gPosTicks(), part->gOffset(), master, met0, met1);
	  tmp->sNext(myGroup);
	} else {
	  firstGroup = myGroup;
	}
      } else {
	myGroup = myGroup->append(note,part->gOffset(),master,met0,met1);
      }
    }
    
    atom = atom->gNext();
    
    
  }
  
  
  // now everything is packed up in groups, lets pack the
  // groups into bars:
  
  
  if (firstGroup) {
    firstBar = new ScoreBar(firstGroup);
    ScoreBar * curBar = firstBar;
    for (myGroup = firstGroup->Next(); myGroup!=0; myGroup = myGroup->Next()) {
      curBar = curBar->append(myGroup,master,met0,met1);
    }
    
  }
  

  
  
  // for (int i=0;i<parts;i++) myBar[i] = firstBar[i];
  myBar = firstBar;
  int loop = 1;
  while (loop) {
    cout << "\\Notes";
    relPos = part->gOffset() - lpos;
    myBar->tex(relPos,part->gClef(),master,met0,met1);
    cout << "\\en" << endl << "\\bar" << endl;
    
    for (i=0;i<7;i++) scrSigns[i]=allSigns[part->gKey()+7][i];
    myBar = myBar->Next();
    if (myBar==0) loop = 0;
  }

  / *
    ScoreGroup * tmp;
    KbPosition curPos;
    
    for (myGroup = firstGroup; myGroup!=0;) {
    // myGroup->print();
    oldTimeBar = curBar;
    relPos = part->gOffset() - lpos;
    curPos = myGroup->start() + relPos;
    curMet0 = met0; curMet1 = met1; curPos.gBBT(curBar,curBeat,curTick,master,curMet0,curMet1,true);
    if (oldTimeBar!=curBar) {
    for (i=0;i<7;i++) scrSigns[i]=allSigns[scrKey+7][i];
    //for (i=0;i<curBar-oldTimeBar;i++)
    //	cout << "\\bar" << endl;
    }
    myGroup->tex(relPos,pixPerTick,xoffset,yoffset,scrClef,master,met0,met1);
    tmp = myGroup->Next();
    delete myGroup;
    myGroup = tmp;
    }
  * /
  // DOIT: remove bars and groups, etc !!!
  
  cout << "\\endpiece
\\end{music}
\\endmuflex
\\end{document}" << endl;
  */
  
}



#endif
