#include <iostream>
#include <string>
#include <algorithm>

//#include <valgrind/callgrind.h>

#include "io/generalio.H"
#include "mira/assembly.H"
#include "mira/parameters.H"
#include "mira/maf_parse.H"



using namespace std;


void doAbort()
{
  abort();
}

int main(int argc, char ** argv)
{
  FUNCSTART("main");

  try{
    string datafile="e.maf";
    string refrname="B66P8:1722:275";
    string newrname="S5ITQ:952:982";
    string paramstring="--job=denovo,genome,accurate,iontor";

    vector<MIRAParameters> MPv;
    MIRAParameters::setupStdMIRAParameters(MPv);

    if(!paramstring.empty()){
      MIRAParameters::parse(paramstring.c_str(),MPv);
    }

    ReadPool       greadpool(&MPv);
    list<Contig>   gcontigs;

    // not used, but needed for linking *sigh*
    Manifest manifest;
    Assembly as(manifest,MPv,false);

    MAFParse tmaf(&greadpool, &gcontigs, &MPv);
    vector<uint32> dummy;
    tmaf.load(datafile, ReadGroupLib::SEQTYPE_SANGER, 1, dummy, false);
    greadpool.makeTemplateIDs();

    greadpool.allowNameIndex(true);
    int32 refid=greadpool.getReadIndex(refrname);
    BUGIFTHROW(refid<0,"Ref " << refrname << " not in readpool?");
    int32 newid=greadpool.getReadIndex(newrname);
    BUGIFTHROW(newid<0,"New " << newrname << " not in readpool?");

    AlignedDualSeqFacts adsf;
    // refid, newid,
    //   delta,id1_rightdelta, id2_rightdelta, totallen, id1_direction, id2_direction, score_ratio
    //adsf.publicinit(refid,newid,2,0,9,91,1,1,100);
    int8 dirnewid=-1;
    bool newid_ismulticopy=true;
    adsf.publicinit(newid,refid,193,158,0,403,-1,1,100,0,16,16,16,16);

    cout << adsf << endl;

    Contig::errorstatus_t errstat;
    vector<Align> aligncache;
    for(uint32 i=0; i<ReadGroupLib::SEQTYPE_END; i++) {
      Align a(&MPv[i]);
      aligncache.push_back(a);
    }

    cout << "before\n";
    Contig::setCoutType(Contig::AS_TEXT);
    cout << gcontigs.back();
    gcontigs.back().addRead(aligncache,
			    &adsf,
			    refid,newid,
			    dirnewid,
			    newid_ismulticopy,
			    0,
			    errstat);

    if(errstat.code == Contig::ENOERROR) {
      cout << "read added\n\n";
      Contig::setCoutType(Contig::AS_TEXT);
      cout << gcontigs.back();
    }else{
      cout << "read not added\n\n";
      Contig::setCoutType(Contig::AS_TEXT);
      cout << gcontigs.back();
    }

  }
  catch(Notify n){
    n.handleError("main");
  }
  catch(Flow f){
    cout << "INTERNAL ERROR: Unexpected exception: Flow()\n";
    doAbort();
  }
  catch(const std::bad_alloc & e){
    cout << "Out of memory detected, exception message is: ";
    cout << e.what() << endl;

    if(sizeof(size_t) == sizeof(int32)){
      cout << "\nYou are running a 32 bit executable. Please note that the maximum"
	"\ntheoretical memory a 32 bit programm can use (be it in Linux, Windows or"
	"\nother) is 4 GiB, in practice less: between 2.7 and 3.3 GiB. This is valid"
	"\neven if your machine has hundreds of GiB."
	"\nShould your machine have more that 4 GiB, use a 64 bit OS and a 64 bit"
	"\nversion of MIRA.";
    }

    cout << "\n\nIf you have questions on why this happened, please send the last 1000"
      "\nlines of the output log (or better: the complete file) to the author"
      "\ntogether with a short summary of your assembly project.\n\n";

    doAbort();
  }
  catch(const ios_base::failure & e){
    cout << "Failure in IO stream detected, exception message is: "
	 << e.what() << endl
	 << "\nWe perhaps ran out of disk space or hit a disk quota?\n";
    doAbort();
  }
  catch (exception& e)
  {
    cout << "A 'standard' exception occured (that's NOT normal):\n" << e.what() << "\n\nIf the cause is not immediatly obvious, please contact: bach@chevreux.org\n\n";
    doAbort();
  }
  catch(...){
    cout << "Unknown exception caught, aborting the process.\n\nPlease contact: bach@chevreux.org\n\n";
    doAbort();
  }

  return 0;
}
