#ifndef _TEX_CPP_
#define _TEX_CPP_

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

#include <reference.h>
#include <table.h>
#include <event.h>
#include <part.h>
#include <note.h>
#include <track.h>
#include <scoreTrack.h>
#include <song.h>
#include <str.h>
#include <position.h>
#include <prMainEditor.h>
#include "../../presentations/kde/qtScoreAddons.h"

#include "tex.h"

extern int globalStaffCounter;
extern PrMainEditor * mainEditor;


extern Song * sonG;

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


extern Table * selectioN;
extern Table * selectionMemory;

// #define TEX_CONTEXT Addon::TREAT_SELECTION + Addon::TREAT_TRACK + Addon::TREAT_PART + Addon::TREAT_SONG
#define TEX_CONTEXT Addon::TREAT_TRACK + Addon::TREAT_PART

extern "C" {
  Addon * tex(Element * target) { return new Tex(target); }
  const char  * tex_name()     { return "tex"; }
  const char  * tex_category() { return "output"; }
  int     tex_context() { return TEX_CONTEXT; }
}


Tex::Tex(Element * target) : Addon("tex", target, !TO_BE_UNDONE, TEX_CONTEXT) {
  const char * filename = mainEditor->filename();
  if ((filename!=0)&&(strlen(filename)>0)) {
    char * fname = (char*) strdup(filename);
    int flen = strlen(fname);
    sprintf(fname+flen-3, "tex");
    // ofstream out(fname);
    // outptr = &out;
    outptr = &cout;
    run();
    // outptr->close();
    free(fname);
  }
}

Tex::~Tex() {

}

void Tex::selection(Table * selection) {
}

void Tex::part(Part * part) {
  // KbMain * main = part->gTrack()->gMain();
  master = sonG->master();
  met0 = sonG->meter0();
  met1 = sonG->meter1();


  QtScoreGroup * firstGroup = 0;
  QtScoreGroup * tmp = 0;
  ScoreTrack * scTrack;
  NoteBar * firstBar = 0;
  NoteBar * myBar;

  (*outptr) << "\\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->meter0() << "}{" << part->meter1() << "}}
\\generalsignature{" << part->key() << "}";


  scTrack = (ScoreTrack*) part->track();

  (*outptr) << "\\setname1{" << scTrack->name() << "}
\\setstaffs1{1}";



  (*outptr) << "\\startpiece" << endl;

  Position relPos = 0;
  Position lpos = 0; //posLeft;

  int i=0;
  for (i=0;i<7;i++) scrSigns[i]=allSigns[part->key()+7][i];

  QtScoreGroup * myGroup = 0;
  // lpos = 0;
  Element* atom = part->first();
  while (atom!=0) {
    if (atom->isA()==NOTE) {
      Note * note = (Note*) atom;
      if (myGroup == 0) {
	relPos = lpos - part->start();
	myGroup = new NoteGroup(note,part->start());
	if (note->internalStart()-relPos > 0) {
	  createBreakGroups(firstGroup, tmp, relPos, note->internalStart()-relPos.ticks(), part->start(), master, met0, met1);
	  tmp->sNext(myGroup);
	} else {
	  firstGroup = myGroup;
	}
      } else {
	myGroup = myGroup->append(note,part->start(),master,met0,met1);
      }
    }

    atom = next(atom);


  }


  // now everything is packed up in groups, lets pack the
  // groups into bars:


  if (firstGroup) {
    firstBar = new NoteBar(firstGroup);
    NoteBar * 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) {
    (*outptr) << "\\Notes";
    relPos = part->start() - lpos;
    myBar->tex(relPos,part->clef(),master,met0,met1);
    (*outptr) << "\\en" << endl << "\\bar" << endl;

    for (i=0;i<7;i++) scrSigns[i]=allSigns[part->key()+7][i];
    myBar = myBar->Next();
    if (myBar==0) loop = 0;
  }

  /*
    QtScoreGroup * 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++)
    //	(*outptr) << "\\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 !!!

  (*outptr) << "\\endpiece
\\end{music}
\\endmuflex
\\end{document}" << endl;

}

void Tex::track(Track * track) {
  master = sonG->master();
  met0 = sonG->meter0();
  met1 = sonG->meter1();

  QtScoreGroup * firstGroup = 0;
  // QtScoreGroup * tmp = 0;

  Part * partList[128];
  Part * part;
  int scrKey = 0;
  int scrClef = 0;
  int parts = 0;
  int N = 0;
  int i = 0;
  for (Track * tr=track; tr!=0; tr=(Track*)tr->next(tr)) {
    if ((tr->first()!=0) && (tr->mute()==FALSE) && (tr->isA()==0)) {
      partList[parts] = (Part*) tr->first();
      parts++;
    }
  }

  ScoreTrack * scTrack;
  NoteBar * firstBar[parts];
  NoteBar * myBar[parts];

  (*outptr) << "\\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]->meter0() << "}{" << partList[0]->meter1() << "}}
\\generalsignature{" << partList[0]->key() << "}";


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

    scTrack = (ScoreTrack*) part->track();

    (*outptr) << "\n\\setname" << pNum << "{" << scTrack->name() << "}
\\setstaffs" << pNum << "{1}";
  }


  (*outptr) << "\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];

    QtScoreGroup * 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 NoteBar(firstGroup);
      NoteBar * 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
  */



    Position relPos = 0;
    Position 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];

      QtScoreGroup * myGroup = 0;
      QtScoreGroup * tmp = 0;
      lpos = 0; //posLeft;
      relPos = lpos - part->start();
      Element* atom = part->first();
      while (atom!=0) {
	if (atom->isA()==NOTE) {
	  Note * note = (Note*) atom;
	  if (myGroup == 0) {
	    // (*outptr) << "soieses" << endl;
	    myGroup = new NoteGroup(note,part->start());
	    if (note->internalStart()-relPos > 0) {
	      /*if (relPos.negative()>0)
		createBreakGroups(firstGroup, tmp, lpos, note->start()+relPos.negative(), part->start(), master, met0, met1);
		else*/
		createBreakGroups(firstGroup, tmp, lpos, note->internalStart()-relPos.ticks(), part->start(), master, met0, met1);
	      tmp->sNext(myGroup);
	    } else {
	      firstGroup = myGroup;
	    }
	  } else {
	    myGroup = myGroup->append(note,part->start(),master,met0,met1);
	  }
	}
	
	atom = part->next(atom);
	
	/*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 NoteBar(firstGroup);
	NoteBar * 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) {
    (*outptr) << count++ << endl;
    for (int i=0;i<parts;i++) {
      (*outptr) << "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) {
    // (*outptr) << count++ << endl;
    (*outptr) << "\\Notes";
    for (int i=0;i<parts;i++) {
      scrKey = partList[i]->key();
      for (int ii=0;ii<7;ii++) scrSigns[ii]=allSigns[scrKey+7][ii];
      if (i>0) (*outptr) << " | ";
      relPos = partList[i]->start() - lpos;
      myBar[i]->tex(relPos,scrClef,master,met0,met1);
    }
    (*outptr) << "\\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;
  }

  /*
    QtScoreGroup * 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++)
    //	(*outptr) << "\\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 !!!

  (*outptr) << "\\endextract
\\end{music}
\\endmuflex
\\end{document}" << endl;






  /*
  QtScoreGroup * firstGroup = 0;
  QtScoreGroup * tmp = 0;
  KbScoreTrack * scTrack;
  NoteBar * firstBar;
  NoteBar * myBar;

  (*outptr) << "\\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();

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



  (*outptr) << "\\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];

  QtScoreGroup * 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 NoteBar(firstGroup);
    NoteBar * 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) {
    (*outptr) << "\\Notes";
    relPos = part->gOffset() - lpos;
    myBar->tex(relPos,part->gClef(),master,met0,met1);
    (*outptr) << "\\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;
  }

  / *
    QtScoreGroup * 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++)
    //	(*outptr) << "\\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 !!!

  (*outptr) << "\\endpiece
\\end{music}
\\endmuflex
\\end{document}" << endl;
  */

}

void Tex::song(Song * song) {

}

void Tex::undo() {
}

void Tex::redo() {
}






#endif
