/*
 *
 * Notice that all coordinates in .gtf file is 1-based, but in prediction files, start coordinates are 0-based, and end coordinates are 1-based.
 */
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>

using namespace std;

bool verbose=false;

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

  cerr<<"This program is used to convert IsoInfer prediction into gene annotation (.gtf) file.\n";
  if(argc<2){
    cerr<<"Error: Isoinfer prediction file needed.\n";
    cerr<<"Usage: pred2gtf [options] isoinferpredfiles\n";
    cerr<<"Options:\n";
    cerr<<"\t-v  Verbose output.\n";
    cerr<<"\t-o [output file] Specify the output file. \n";
    cerr<<"Note:\n";
    cerr<<"\tLines beginning with @ will be ignored.\n";
    cerr<<"\t- stands for standard out.\n";
    return -1;
  }

  string ifsname(argv[argc-1]);
  string ofsname="-";
  for(int i=1;i<argc;i++){
    if(string(argv[i])=="-v"){
      verbose=true;
      cerr<<"Using verbose output...\n";
    }
    if(string(argv[i])=="-o" && i<argc-1){
      ofsname=string(argv[i+1]);
    }
  }

  ifstream ifs;
  ofstream ofs;
  
  bool inputfromfile;
  bool outputfromfile;
  
  if(ifsname!="-"){
    ifs.open(ifsname.c_str());
    if(!ifs.is_open()){
      cerr<<"Error opening files "<<ifsname<<endl;
      return -1;
    }
    inputfromfile=true;
  }else{
    inputfromfile=false;
  }
  
  ostream* pout;
  if(ofsname!="-"){
    ofsname=ifsname+".gtf";
    ofs.open(ofsname.c_str());
    if(!ofs.is_open()){
      cerr<<"Error opening files "<<ofsname<<endl;
      return -1;
    }
    outputfromfile=true;
    pout=&(ofs);
  }else{
    outputfromfile=false;
    pout=&cout;
  }

  vector<long> startpos,endpos;
  long nline=0;
  while(!ifs.eof()){
    string oneline;
    if(inputfromfile){
      getline(ifs,oneline);
      if(ifs.eof())break;
    }else{
      getline(cin,oneline);
      if(cin.eof())break;
    }
    if(oneline[0]=='#')continue; // skip comment line
    if(verbose)cerr<<"Processing line "<<nline++<<"..."<<endl;
    stringstream ss(oneline);
    //parse one line
    string instid;string predid;string chrom; char strand; long startt,endt;
    double explv=-1;
    startpos.clear();
    endpos.clear();
    string startstr,endstr;
    ss>>instid>>predid>>chrom>>strand>>startt>>endt>>startstr>>endstr;
    ss>>explv;
    if(ss.fail())explv=1;
    if(verbose)cerr<<"start: "<<startstr<<endl;
    if(verbose)cerr<<"end: "<<endstr<<endl;
    //parse startstr and endstr
    stringstream ss2(startstr);
    do{
      long tmpl;
      ss2>>tmpl;
      startpos.push_back(tmpl);
      char tc;
      ss2>>tc;
    }while(!ss2.eof());
    stringstream ss3(endstr);
    do{
      long tmpl;
      ss3>>tmpl;
      endpos.push_back(tmpl);
      char tc;
      ss3>>tc;
    }while(!ss3.eof());
    if(endpos.size()!=startpos.size()){
      cerr<<"Error: not equal number of start pos and end pos elements.\n";
    }
    //write to output
    (*pout)<<chrom<<"\t"<<"IsoInfer\ttranscript\t"<<startt+1<<"\t"<<endt<<"\t";
    //score, guess 1000
    (*pout)<<1000<<"\t";
    //strand and frame
    (*pout)<<strand<<"\t.\t";
    //annotation
    string anno="gene_id \"Inst"+instid+"\"; transcript_id \""+predid+"\"; ";
    stringstream anno2s;
    anno2s<<"FPKM  \""<<explv<<"\"; frac \"1.000000\"; conf_lo \"0.0\"; conf_hi \"2.0\"; cov \"0.1\";";
    string anno2=anno2s.str();
    (*pout)<<anno<<anno2<<endl;
    
    //we need to merge continuous exons here
    int leftpos=0,rightpos=0;
    int exonnum=1;
    while(leftpos<startpos.size()){
      rightpos=leftpos;
      while(rightpos+1<endpos.size() && endpos[rightpos]==startpos[rightpos+1]){
        rightpos++;
      }
      //write to output
      (*pout)<<chrom<<"\t"<<"IsoInfer\texon\t"<<startpos[leftpos]+1<<"\t"<<endpos[rightpos]<<"\t";
      //score, guess 1000
      (*pout)<<1000<<"\t";
      //strand and frame
      (*pout)<<strand<<"\t.\t";
      (*pout)<<anno<<"exon_number \""<<exonnum<<"\"; "<<anno2<<endl;
      leftpos=rightpos+1;
      exonnum++;
    }
  }

  if(outputfromfile)
    ofs.close();
  if(inputfromfile)
    ifs.close();
  return 0;
}
