#include "seeKaryo.h"

// Customizable parameters
int fbsizeX = 600;
int fbsizeY = 800;
int linesPerGene = 2;
int chrFeatID = 1;
int mbFeatID = 2;

void setchrFeatID(int ID) {
  chrFeatID = ID;
}

void setmbFeatID(int ID) {
  mbFeatID = ID;
}

void setLinesPerGene(int size) {
  linesPerGene = size;
}

void setfbSize(int sizeX, int sizeY) {
  fbsizeX = sizeX;
  fbsizeY = sizeY;
}


//------------------------------------------------------------------------
// Color entire graph based on a feature
//------------------------------------------------------------------------
void colorByFeature (graph* g, int featureNum) {
  int v1;
  float min,max,featureValue;

  if(featureNum>g->numVertFeatures) {
    fprintf(stderr," colorByFeature(%d): No such feature present\n",featureNum);
    return;
  }

  getMinMax(g,featureNum,&min,&max);
  for(v1=0;v1<g->numVerts;v1++) {
    featureValue = g->vertData[v1*(g->numVertFeatures+1)+featureNum];
    Normalize1f(min,max, 0.f,255.f, &featureValue);
    g->vertColorList[v1]=(int)featureValue;
  }
}

void lineRastH(int x, int y, int length, int szX, int szY,
               int colorID, float** clut, unsigned char * framebuffer) {
  register int i, index;

  for(i=x;i<x+length;i++) {
     index = 3*(y*szX+i);
     framebuffer[index  ] = (unsigned char)(clut[colorID][0]*255.f);
     framebuffer[index+1] = (unsigned char)(clut[colorID][1]*255.f);
     framebuffer[index+2] = (unsigned char)(clut[colorID][2]*255.f);
  }
}

void lineRastV(int x, int y, int length, int szX, int szY,
               int colorID, float** clut, unsigned char * framebuffer) {
  register int i, index;

  for(i=y;i<y+length;i++) {
     index = 3*(i*szX+x);
     framebuffer[index  ] = (unsigned char)(clut[colorID][0]*255.f);
     framebuffer[index+1] = (unsigned char)(clut[colorID][1]*255.f);
     framebuffer[index+2] = (unsigned char)(clut[colorID][2]*255.f);
  }
}

int writeKaryo(char* filename, graph* g, float** tlut, int featureNum) {
   int i, j;
   int chrID;

   // Image data
   int chrSpacing = 10;
   int chrWidth = 20;
   int chrHeight = 600;
   int chrStartY = 10;
   double stretchY = -1.0;
   int drawX, drawY,height,max;
   int *chrStart;
   unsigned char *framebuffer;

   // Command line parameters
   FILE* fpCLF;
   char* clfFilename;
   char* extension;

   // Input chromosome layout file
   float *mb, *gmb;
   int numChroms = -1;

   // Read the chromosome layout file (assumes 3 letter extension)
   clfFilename=(char*)malloc( (strlen(g->name)+1) * sizeof(char));
   if(clfFilename==NULL) {perror("malloc clfFilename:"); return -1;}
   strcpy(clfFilename,g->name);
	 extension=clfFilename+(strlen(clfFilename)-4);
	 strcpy(extension,".clf");

   fpCLF = fopen(clfFilename, "r");
   if(fpCLF == NULL) {
      fprintf(stderr,"  Can't find file: %s\n",clfFilename);
      return -1;
   }
   fscanf(fpCLF,"%d\n",&numChroms);
   mb = (float*)malloc(numChroms*sizeof(float));
   gmb = (float*)malloc(numChroms*sizeof(float));
   if(mb==NULL || gmb==NULL) {
     perror("malloc mb/gmb");
     return -1;
   }
   for(i=0;i<numChroms;i++) {
    fscanf(fpCLF,"%d\t",&chrID);
    if(chrID<1) {
      fprintf(stderr," Bad Chromosome ID %d in %s\n",chrID,clfFilename);
      return -1;
    }
    chrID--; //base 1 to base 0
    fscanf(fpCLF,"%f\t%f\n",&(mb[chrID]),&(gmb[chrID]));
   }
   fclose(fpCLF);
   free(clfFilename);

   // Color the vertices
   colorByFeature(g,featureNum);

   // Generate the start and end position of each chromosome
   chrStart = (int*)malloc(2*numChroms*sizeof(int));
   if(chrStart==NULL) {
     perror("malloc chrStart");
     return -1;
   }
   for(i=0;i<numChroms;i++) {
     chrStart[2*i  ] = i*chrWidth+i*chrSpacing+chrSpacing/2;
     chrStart[2*i+1] = chrStartY;
   }
   max=1;
   for(i=0;i<numChroms;i++) {
     if( (int)mb[i]>max ) max=(int)mb[i];
   }
   stretchY = (fbsizeY-chrStartY*2)/(float)max;

   // Draw the data
   framebuffer = (unsigned char *)malloc(sizeof(unsigned char)*fbsizeY*fbsizeX*3);
   if(framebuffer==NULL) {
     perror("malloc framebuffer");
     return -1;
   }
   for(i=0;i<g->numDisplayVerts;i++) {
     chrID = (int)g->vertData[g->vertList[i]*(g->numVertFeatures+1)+chrFeatID];
	 if(chrID < 0 || chrID > numChroms)
		 continue;
     chrID--; //base 1 to base 0
     drawX = chrStart[2*chrID  ];
     drawY = chrStart[2*chrID+1];
     drawY += (int)(g->vertData[g->vertList[i]*(g->numVertFeatures+1)+mbFeatID]*stretchY);
     if(drawX<0 || drawY<0 || drawX>fbsizeX || drawY>fbsizeY) {
       fprintf(stderr,"  Problem drawing karyo - aborted == %d, %f, %f\n",chrID,g->vertData[g->vertList[i]*(g->numVertFeatures+1)+chrFeatID],g->vertData[g->vertList[i]*(g->numVertFeatures+1)+mbFeatID]);
       return -1;
     }
     for(j=-linesPerGene/2;j<=linesPerGene/2;j++) {
       lineRastH(drawX, drawY+j, chrWidth, fbsizeX, fbsizeY,
                 g->vertColorList[g->vertList[i]], tlut, framebuffer);
     }
   }

   // Draw borders
   for(i=0;i<numChroms;i++) {
     drawX = chrStart[2*i  ];
     drawY = chrStart[2*i+1];
     height = (int)(mb[i]*stretchY);

     //index 50 ~black but changes with default.lut
     //bottom
     lineRastH(drawX, drawY-1, chrWidth+1,
               fbsizeX, fbsizeY, 50, tlut, framebuffer);
     //top
     lineRastH(drawX, drawY+height+1, chrWidth+1,
               fbsizeX, fbsizeY, 50, tlut, framebuffer);
     //left
     lineRastV(drawX, drawY, height+1,
               fbsizeX, fbsizeY, 50, tlut, framebuffer);
     //right
     lineRastV(drawX+chrWidth, drawY, height+1,
               fbsizeX, fbsizeY, 50, tlut, framebuffer);
   }

   // Create the image file
   vcbImgWriteBMP(filename, framebuffer, 3, fbsizeX, fbsizeY);

   free(mb); free(gmb);
   free(chrStart);
   free(framebuffer);
   //scanf(filename);
   return 0;
}
