//
// Programmer:    Craig Stuart Sapp <craig@ccrma.stanford.edu>
// Creation Date: 26 Dec 2000
// Last Modified: 26 Dec 2000
// Filename:      ...sig/examples/all/eised.cpp
// Web Address:   http://sig.sapp.org/examples/museinfo/humdrum/eised.cpp
// Syntax:        C++; museinfo
//
// Description:   data field extract/insert program
//

#include "humdrum.h"

#include <string.h>
#include <stdio.h>

#ifndef OLDCPP
   #include <iostream>
   using namespace std;
#else
   #include <iostream.h>
#endif


// function declarations
void      checkOptions(Options& opts, int argc, char* argv[]);
void      example(void);
void      usage(const char* command);

void      replaceDataInterp(Array<int>& interpList);     
void      replaceDataField(Array<int>& fieldList);     
void      replaceDataAll(void);
void      generateDataField(Array<int>& fieldList);     
void      generateDataInterp(Array<int>& interpList);     
void      generateDataAll(void);
void      generateFieldList(const char* fieldstring);
void      generateInterpList(const char* interpstring);


// global variables
Options   options;            // database for command-line arguments
Array<int> fieldList;         // used with the -f option
Array<int> interpList;        // used with the -i option
int maxfield = 0;             // used with the -f option
int ilistQ = 0;               // used with the -i option
int flistQ = 0;               // used with the -f option
int measureQ = 0;             // used with the -m option

///////////////////////////////////////////////////////////////////////////

int main(int argc, char* argv[]) {
   HumdrumFile infile;

   // process the command-line options
   checkOptions(options, argc, argv);

   // figure out the number of input files to process
   int numinputs = options.getArgCount();

   if (numinputs < 1) {
      usage(options.getCommand());
      exit(1);
   }

   if (cin.peek()) {
      if (ilistQ) {
         replaceDataInterp(interpList);     
      } else if (flistQ) {
         replaceDataField(fieldList);     
      } else {
         replaceDataAll();
      }
   } else {
      if (ilistQ) {
         generateDataInterp(interpList);     
      } else if (flistQ) {
         generateDataField(fieldList);     
      } else {
         generateDataAll();
      }
   }

   return 0;
}


///////////////////////////////////////////////////////////////////////////


//////////////////////////////
//
// checkOptions -- validate and process command-line options.
//

void checkOptions(Options& opts, int argc, char* argv[]) {
   opts.define("i|interpretation=s", "Exclusive interpretations to process");
   opts.define("f|field=s", "Fields to process");
   opts.define("m|measure=s", "include measures in data processing");

   opts.define("debug=b",             "determine bad input line num");
   opts.define("author=b",            "author of program");
   opts.define("version=b",           "compilation info");
   opts.define("example=b",           "example usages");
   opts.define("h|help=b",            "short description");
   opts.process(argc, argv);
   
   // handle basic options:
   if (opts.getBoolean("author")) {
      cout << "Written by Craig Stuart Sapp, "
           << "craig@ccrma.stanford.edu, October 2000" << endl;
      exit(0);
   } else if (opts.getBoolean("version")) {
      cout << argv[0] << ", version: 15 October 2000" << endl;
      cout << "compiled: " << __DATE__ << endl;
      cout << MUSEINFO_VERSION << endl;
      exit(0);
   } else if (opts.getBoolean("help")) {
      usage(opts.getCommand());
      exit(0);
   } else if (opts.getBoolean("example")) {
      example();
      exit(0);
   }

   fieldList.setSize(0);
   fieldList.allowGrowth(1);
   interpList.setSize(0);
   interpList.allowGrowth(1);
   if (opts.getBoolean("interpretation")) {
      ilistQ = 1;
      flistQ = 0;
      generateInterpList(opts.getString("interpretation"));
   } else if (opts.getBoolean("field")) {
      flistQ = 1;
      ilistQ = 0;
      generateFieldList(opts.getString("fields"));
   } else {
      flistQ = 0;
      ilistQ = 0;
   }

   if (opts.getBoolean("measure")) {
      measureQ = 1;
   } else {
      measureQ = 0;
   }

}
  


//////////////////////////////
//
// example -- example usage of the quality program
//

void example(void) {
   cout <<
   "                                                                         \n"
   "# example usage of the spinetrace program.                               \n"
   "     spinetrace chor217.krn                                              \n"
   "                                                                         \n"
   << endl;
}



//////////////////////////////
//
// usage -- gives the usage statement for the meter program
//

void usage(const char* command) {
   cout <<
   "                                                                         \n"
   << endl;
}


//////////////////////////////////////////////////////////////////////////

///////////////////////////////
//
//  replaceDataInterp --
//

void replaceDataInterp(Array& interpList) {

}



///////////////////////////////
//
//  replaceDataField --
//

void replaceDataField(Array& fieldList) {

}



///////////////////////////////
//
//  replaceDataAll --
//

void replaceDataAll(void) {
   char buffer[10000] = {0};
   int i, j, f;
   HumdrumFile file;
   for (f=0; f<options.getArgCount(); f++) {
      file.clear();
      file.read(options.getArg(f+1));
      for (i=0; i<file.getNumLines(); i++) {
         if (file[i].getType() != E_humrec_data && 
             file[i].getType() != E_humrec_data_measure) {
            continue;
         }
         if (measureQ && file[i].getType() == E_humrec_data_measure) {
         } else {
            continue;
         }
   
         for (j=0; j<file[i].getFieldCount(); j++) {
            cin.getline(buffer, 512, '\n');
            file[i].changeField(j, buffer);
         }
      }
   }
}



///////////////////////////////
//
//  replaceDataInterp --
//

void generateDataField(Array& fieldList) { 
   Array<int> includelist;
   includelist.setSize(maxfield+1);
   includelist.zero();
   int i, j, f;
   for (i=0; i<fieldList.getSize(); i++) {
      includelist[fieldList[i]] = 1;
   }

   HumdrumFile file;
   char buffer[10000] = {0};
   int fieldnum;
   int found;
   int index;
   char* ptr;
   for (f=0; f<options.getArgCount(); f++) {
      file.clear();
      file.read(options.getArg(f+1));
      for (i=0; i<file.getNumLines(); i++) {
         if (file[i].getType() != E_humrec_data && 
            file[i].getType() != E_humrec_data_measure) {
            continue;
         }
         if (measureQ && file[i].getType() == E_humrec_data_measure) {
         } else {
            continue;
         }
   
         for (j=0; j<file[i].getFieldCount(); j++) {
            fieldnum = file[i].getExInterpNum(j);
            found = 0;
            strcpy(buffer, file[i].getSpineInfo(j));
            ptr = strtok(buffer, "() ab");
            while (ptr != NULL) {
               index = atoi(ptr);
               if (includelist[index]) {
                  found = 1;
                  break;
               }
               ptr = strtok(NULL, "() ab");
            }
            if (found) {
               cout << file[i][j] << "\n";
            }
         }
      }
   }
}



///////////////////////////////
//
//  generateDataInterp --
//

void generateDataInterp(Array& interpList) {
   int i, j, f;
   HumdrumFile file;
   int interpnum;
   int found;
   int k;
   for (f=0; f<options.getArgCount(); f++) {
      file.clear();
      file.read(options.getArg(f+1));
      for (i=0; i<file.getNumLines(); i++) {
         if (file[i].getType() != E_humrec_data && 
             file[i].getType() != E_humrec_data_measure) {
            continue;
         }
         if (measureQ && file[i].getType() == E_humrec_data_measure) {
         } else {
            continue;
         }
   
         for (j=0; j<file[i].getFieldCount(); j++) {
            interpnum = file[i].getExInterpNum(j);
            found = 0;
            for (k=0; k<interpList.getSize(); k++) {
               if (interpnum == interpList[k]) {
                  found = 1;
                  break;
               }
            }
            if (found) {
               cout << file[i][j] << "\n";
            }
         }
      }
   }
}



///////////////////////////////
//
//  generateDataAll --
//

void generateDataAll(void) {
   int i, j, f;
   HumdrumFile file;
   for (f=0; f<options.getArgCount(); f++) {
      file.clear();
      file.read(options.getArg(f+1));
      for (i=0; i<file.getNumLines(); i++) {
         if (file[i].getType() != E_humrec_data && 
             file[i].getType() != E_humrec_data_measure) {
            continue;
         }
         if (measureQ && file[i].getType() == E_humrec_data_measure) {
         } else {
            continue;
         }
   
         for (j=0; j<file[i].getFieldCount(); j++) {
            cout << file[i][j] << "\n";
         }
      }
   }
}


//////////////////////////////
//
// generateFieldList --
//

void generateFieldList(const char* fieldstring) {
   maxfield = 0;
   int length = strlen(fieldstring);
   char* buffer = new char[length+1];
   strcpy(buffer, fieldstring);
   int starti, stopi;
   int temp;
   int num;
   char* ptr = strtok(buffer, " ,;:");
   while (ptr != NULL) {
      if (strchr(ptr, '-') != NULL) {
         sscanf(ptr, "%d-%d", &starti, &stopi);
         if (starti > stopi) {
            temp = starti;
            starti=stopi;
            stopi = temp;
         } 
         for (num=starti; num<=stopi; num++) {
            fieldList.append(num);
         }
         if (num > maxfield) {
            maxfield = num;
         }
      } else {
         sscanf(ptr, "%d", &num);
         fieldList.append(num);
         if (num > maxfield) {
            maxfield = num;
         }
      }
      ptr = strtok(NULL, " ,;:");
   }

}



//////////////////////////////
//
// generateInterpList --
//

void generateInterpList(const char* interpstring) {
   int length = strlen(interpstring);
   char* buffer = new char[length+1];
   strcpy(buffer, interpstring);
   char* ptr = strtok(buffer, " \t,");
   int num;
   while (ptr != NULL) {
      // convert exstring to number
      num = Convert::exint.getValue(ptr);
      interpList.append(num);
      ptr = strtok(NULL, " ,;:");
   }
}


// md5sum: 4a7eb17b2331e246a2f4dfaea48076aa eised.cpp [20050403]