/* bigPsl.c was originally generated by the autoSql program, which also 
 * generated bigPsl.h and bigPsl.sql.  This module links the database and
 * the RAM representation of objects. */

#include "common.h"
#include "linefile.h"
#include "dystring.h"
#include "jksql.h"
#include "bigPsl.h"
#include "psl.h"



char *bigPslCommaSepFieldNames = "chrom,chromStart,chromEnd,name,score,strand,thickStart,thickEnd,reserved,blockCount,blockSizes,chromStarts,oChromStart,oChromEnd,oStrand,oChromSize,oChromStarts,oSequence,oCDS,chromSize,match,misMatch,repMatch,nCount";

struct bigPsl *bigPslLoad(char **row)
/* Load a bigPsl from row fetched with select * from bigPsl
 * from database.  Dispose of this with bigPslFree(). */
{
struct bigPsl *ret;

AllocVar(ret);
ret->blockCount = sqlSigned(row[9]);
ret->chrom = cloneString(row[0]);
ret->chromStart = sqlUnsigned(row[1]);
ret->chromEnd = sqlUnsigned(row[2]);
ret->name = cloneString(row[3]);
ret->score = sqlUnsigned(row[4]);
safecpy(ret->strand, sizeof(ret->strand), row[5]);
ret->thickStart = sqlUnsigned(row[6]);
ret->thickEnd = sqlUnsigned(row[7]);
ret->reserved = sqlUnsigned(row[8]);
{
int sizeOne;
sqlSignedDynamicArray(row[10], &ret->blockSizes, &sizeOne);
assert(sizeOne == ret->blockCount);
}
{
int sizeOne;
sqlSignedDynamicArray(row[11], &ret->chromStarts, &sizeOne);
assert(sizeOne == ret->blockCount);
}
ret->oChromStart = sqlUnsigned(row[12]);
ret->oChromEnd = sqlUnsigned(row[13]);
safecpy(ret->oStrand, sizeof(ret->oStrand), row[14]);
ret->oChromSize = sqlUnsigned(row[15]);
{
int sizeOne;
sqlSignedDynamicArray(row[16], &ret->oChromStarts, &sizeOne);
assert(sizeOne == ret->blockCount);
}
ret->oSequence = cloneString(row[17]);
ret->oCDS = cloneString(row[18]);
ret->chromSize = sqlUnsigned(row[19]);
ret->match = sqlUnsigned(row[20]);
ret->misMatch = sqlUnsigned(row[21]);
ret->repMatch = sqlUnsigned(row[22]);
ret->nCount = sqlUnsigned(row[23]);
return ret;
}

struct bigPsl *bigPslLoadAll(char *fileName) 
/* Load all bigPsl from a whitespace-separated file.
 * Dispose of this with bigPslFreeList(). */
{
struct bigPsl *list = NULL, *el;
struct lineFile *lf = lineFileOpen(fileName, TRUE);
char *row[24];

while (lineFileRow(lf, row))
    {
    el = bigPslLoad(row);
    slAddHead(&list, el);
    }
lineFileClose(&lf);
slReverse(&list);
return list;
}

struct bigPsl *bigPslLoadAllByChar(char *fileName, char chopper) 
/* Load all bigPsl from a chopper separated file.
 * Dispose of this with bigPslFreeList(). */
{
struct bigPsl *list = NULL, *el;
struct lineFile *lf = lineFileOpen(fileName, TRUE);
char *row[24];

while (lineFileNextCharRow(lf, chopper, row, ArraySize(row)))
    {
    el = bigPslLoad(row);
    slAddHead(&list, el);
    }
lineFileClose(&lf);
slReverse(&list);
return list;
}

struct bigPsl *bigPslCommaIn(char **pS, struct bigPsl *ret)
/* Create a bigPsl out of a comma separated string. 
 * This will fill in ret if non-null, otherwise will
 * return a new bigPsl */
{
char *s = *pS;

if (ret == NULL)
    AllocVar(ret);
ret->chrom = sqlStringComma(&s);
ret->chromStart = sqlUnsignedComma(&s);
ret->chromEnd = sqlUnsignedComma(&s);
ret->name = sqlStringComma(&s);
ret->score = sqlUnsignedComma(&s);
sqlFixedStringComma(&s, ret->strand, sizeof(ret->strand));
ret->thickStart = sqlUnsignedComma(&s);
ret->thickEnd = sqlUnsignedComma(&s);
ret->reserved = sqlUnsignedComma(&s);
ret->blockCount = sqlSignedComma(&s);
{
int i;
s = sqlEatChar(s, '{');
AllocArray(ret->blockSizes, ret->blockCount);
for (i=0; i<ret->blockCount; ++i)
    {
    ret->blockSizes[i] = sqlSignedComma(&s);
    }
s = sqlEatChar(s, '}');
s = sqlEatChar(s, ',');
}
{
int i;
s = sqlEatChar(s, '{');
AllocArray(ret->chromStarts, ret->blockCount);
for (i=0; i<ret->blockCount; ++i)
    {
    ret->chromStarts[i] = sqlSignedComma(&s);
    }
s = sqlEatChar(s, '}');
s = sqlEatChar(s, ',');
}
ret->oChromStart = sqlUnsignedComma(&s);
ret->oChromEnd = sqlUnsignedComma(&s);
sqlFixedStringComma(&s, ret->oStrand, sizeof(ret->oStrand));
ret->oChromSize = sqlUnsignedComma(&s);
{
int i;
s = sqlEatChar(s, '{');
AllocArray(ret->oChromStarts, ret->blockCount);
for (i=0; i<ret->blockCount; ++i)
    {
    ret->oChromStarts[i] = sqlSignedComma(&s);
    }
s = sqlEatChar(s, '}');
s = sqlEatChar(s, ',');
}
ret->oSequence = sqlStringComma(&s);
ret->oCDS = sqlStringComma(&s);
ret->chromSize = sqlUnsignedComma(&s);
ret->match = sqlUnsignedComma(&s);
ret->misMatch = sqlUnsignedComma(&s);
ret->repMatch = sqlUnsignedComma(&s);
ret->nCount = sqlUnsignedComma(&s);
*pS = s;
return ret;
}

void bigPslFree(struct bigPsl **pEl)
/* Free a single dynamically allocated bigPsl such as created
 * with bigPslLoad(). */
{
struct bigPsl *el;

if ((el = *pEl) == NULL) return;
freeMem(el->chrom);
freeMem(el->name);
freeMem(el->blockSizes);
freeMem(el->chromStarts);
freeMem(el->oChromStarts);
freeMem(el->oSequence);
freeMem(el->oCDS);
freez(pEl);
}

void bigPslFreeList(struct bigPsl **pList)
/* Free a list of dynamically allocated bigPsl's */
{
struct bigPsl *el, *next;

for (el = *pList; el != NULL; el = next)
    {
    next = el->next;
    bigPslFree(&el);
    }
*pList = NULL;
}

void bigPslOutput(struct bigPsl *el, FILE *f, char sep, char lastSep) 
/* Print out bigPsl.  Separate fields with sep. Follow last field with lastSep. */
{
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->chrom);
if (sep == ',') fputc('"',f);
fputc(sep,f);
fprintf(f, "%u", el->chromStart);
fputc(sep,f);
fprintf(f, "%u", el->chromEnd);
fputc(sep,f);
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->name);
if (sep == ',') fputc('"',f);
fputc(sep,f);
fprintf(f, "%u", el->score);
fputc(sep,f);
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->strand);
if (sep == ',') fputc('"',f);
fputc(sep,f);
fprintf(f, "%u", el->thickStart);
fputc(sep,f);
fprintf(f, "%u", el->thickEnd);
fputc(sep,f);
fprintf(f, "%u", el->reserved);
fputc(sep,f);
fprintf(f, "%d", el->blockCount);
fputc(sep,f);
{
int i;
if (sep == ',') fputc('{',f);
for (i=0; i<el->blockCount; ++i)
    {
    fprintf(f, "%d", el->blockSizes[i]);
    fputc(',', f);
    }
if (sep == ',') fputc('}',f);
}
fputc(sep,f);
{
int i;
if (sep == ',') fputc('{',f);
for (i=0; i<el->blockCount; ++i)
    {
    fprintf(f, "%d", el->chromStarts[i]);
    fputc(',', f);
    }
if (sep == ',') fputc('}',f);
}
fputc(sep,f);
fprintf(f, "%u", el->oChromStart);
fputc(sep,f);
fprintf(f, "%u", el->oChromEnd);
fputc(sep,f);
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->oStrand);
if (sep == ',') fputc('"',f);
fputc(sep,f);
fprintf(f, "%u", el->oChromSize);
fputc(sep,f);
{
int i;
if (sep == ',') fputc('{',f);
for (i=0; i<el->blockCount; ++i)
    {
    fprintf(f, "%d", el->oChromStarts[i]);
    fputc(',', f);
    }
if (sep == ',') fputc('}',f);
}
fputc(sep,f);
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->oSequence);
if (sep == ',') fputc('"',f);
fputc(sep,f);
if (sep == ',') fputc('"',f);
fprintf(f, "%s", el->oCDS);
if (sep == ',') fputc('"',f);
fputc(sep,f);
fprintf(f, "%u", el->chromSize);
fputc(sep,f);
fprintf(f, "%u", el->match);
fputc(sep,f);
fprintf(f, "%u", el->misMatch);
fputc(sep,f);
fprintf(f, "%u", el->repMatch);
fputc(sep,f);
fprintf(f, "%u", el->nCount);
fputc(sep,f);
fprintf(f, "%u", el->seqType);
fputc(lastSep,f);
}

/* -------------------------------- End autoSql Generated Code -------------------------------- */

struct psl  *pslFromBigPsl( char *chrom, struct bigBedInterval *bb, int seqTypeField,  char **seq, char **cds)
/* build a psl from a bigPsl */
{
char *extra = cloneString(bb->rest);
int numCols = 12 + 13 - 3;
char *row[numCols];
int wordCount = chopByChar(extra, '\t', row, numCols);
if (wordCount < numCols - 1)
    errAbort("pslFromBigPsl: expected at least %d columns in `rest' field, found %d columns", numCols, wordCount);

int seqType = 0;
if (wordCount == numCols)
    seqType = sqlUnsigned(row[21]);

if (seq != NULL)
    *seq = NULL;
if (cds != NULL)
    *cds = NULL;
struct psl *psl;
int ii;
int sizeOne;
boolean isProt = (seqType == PSL_SEQTYPE_PROTEIN);
AllocVar(psl);

psl->qName = cloneString(row[0]); 
psl->strand[0] = *row[2];
if ((cds != NULL) &&  !isEmpty(row[15]))
    *cds = cloneString(row[15]);

if ((seq != NULL) && !isEmpty(row[14]))
    *seq = cloneString(row[14]);
psl->tSize = sqlUnsigned(row[16]);
psl->match = sqlUnsigned(row[17]);
psl->misMatch = sqlUnsigned(row[18]);
psl->repMatch = sqlUnsigned(row[19]);
psl->nCount = sqlUnsigned(row[20]);
psl->tName = cloneString(chrom);
psl->tStart = bb->start;
psl->tEnd = bb->end;
psl->blockCount = sqlSigned(row[6]);
sqlUnsignedDynamicArray(row[7], &psl->blockSizes, &sizeOne);
assert(sizeOne == psl->blockCount);
sqlUnsignedDynamicArray(row[8], &psl->tStarts, &sizeOne);
assert(sizeOne == psl->blockCount);
psl->qStart = sqlSigned(row[9]); 
psl->qEnd = sqlSigned(row[10]); 
psl->strand[1] = *row[11];
psl->strand[2] = 0;
psl->qSize = sqlSigned(row[12]); 
sqlUnsignedDynamicArray(row[13], &psl->qStarts, &sizeOne);
assert(sizeOne == psl->blockCount);
for(ii=0; ii < psl->blockCount; ii++)
    {
    psl->tStarts[ii] += psl->tStart;
    }

// because reference blocks  are always on the positive strand in beds, we need to revComp them
// if the alignment is meant to be on the reference's negative strand
if (isProt)
    for(ii=0; ii < psl->blockCount; ii++)
        psl->blockSizes[ii] /= 3;
if (psl->strand[1] == '-')
    {
    psl->strand[1] = '+';
    pslRc(psl);
    }

pslComputeInsertCounts(psl);
return psl;
}
