#ifndef _SHORT_READ_H_
#define _SHORT_READ_H_

/**
 *    WHAM - high-throughput sequence aligner
 *    Copyright (C) 2011  WHAM Group, University of Wisconsin
 *
 *    This program is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/*	$Id: short.h 157 2012-07-25 05:58:09Z yinan $ */

#include <stdio.h>
#include <string.h>
#include "sequence.h"
#include "bitread.h"
#include "error.h"

typedef int strand;
#define FORWARD 0
#define BACKWARD 1

class ShortRead {
private:
  char ** fnames; /* file names */
  int nFile; /* the number of files */
  bool forward; /* forward scan */
  bool backward; /* backward scan */
  int length; /* length of short read (characters) */

  int nRead;

  //query sequence
  int nReadPerAlign;
  int64 * reads;

  //qname
  bool storeName;
  int lenName;
  char * names;

  //qualities
  bool storeQual;
  int lenQual;
  char * quals;

  //output
  char alFileName[256];
  char unFileName[256];
  FILE * alfile;
  FILE * unfile;

  int sidx[2]; /* mapping strand to offset in array */
  char code2Base[8];
public:
  ShortRead();
  ShortRead(ShortRead * read);
  ~ShortRead();
  int init(char ** files, int numFile, bool fw, bool bw, char * alignFileName,
      char * unalignFileName);
  int load(int maxlen);
  ShortRead ** split(int num);

  inline int getReadLength() {
    return length;
  }

  inline int64 * getRead(int id, strand s = 0) {
    return &reads[id * WORDS_PER_READ * nReadPerAlign + sidx[s] * WORDS_PER_READ];
  }

  inline int getNumReads() {
    return nRead;
  }

  inline char * getRefName(int i) {
    return fnames[i];
  }

  inline char * getReadName(int i) {
    return &names[i * lenName];
  }

  inline char * getQual(int i) {
    return &quals[i * lenQual];
  }

  inline bool isForward() {
    return forward;
  }

  inline bool isBackward() {
    return backward;
  }

  inline char * getAlignFileName() {
    if (alfile)
      return alFileName;
    else
      return NULL;
  }

  inline char * getUnalignFileName() {
    if (unfile)
      return unFileName;
    else
      return NULL;
  }

  inline void printAlign(int i) {
    if (alfile != NULL
      )
      printRead(i, alfile);
  }

  inline void printUnalign(int i) {
    if (unfile != NULL
      )
      printRead(i, unfile);
  }

  void flush() {
    if (alfile != NULL)
    {
      if (fflush(alfile) != 0)
        elog(ERROR, "file error when flush align file.\n");
      if (fclose(alfile) != 0)
        elog(ERROR, "file error when close align file.\n");
    }

    if (unfile != NULL)
    {
      if (fflush(unfile) != 0)
        elog(ERROR, "file error when flush unalign file.\n");
      if (fclose(unfile) != 0)
        elog(ERROR, "file error when close unalign file.\n");
    }
  }

  int getReadNameLength(char * str) {
    char * p;
    p = strchr(str, ' ');
    if (p == NULL
      )
      return strlen(str) + 1;
    else
      return p - str + 1;
  }

  void extractReadName(char * str1, char * str2) {
    char * p;
    p = strchr(str2, ' ');
    if (p != NULL
      )
      *p = '\0';
    strcpy(str1, str2);
  }

private:
  int readLine(FILE * file, char * str, int maxLength);
  int allocate();
  int preProcess(int maxlen);
  void printRead(int id, FILE * file);

};

#endif

