#pragma once
#ifndef SHORT_READ_UTIL_H
#define SHORT_READ_UTIL_H

#include <ctype.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;

//TODO separate inline functions for single base and functions for short Read.

#define NT_SIZE 4

inline bool isACGT(char nt)
{
    switch (nt) {
    case 'a':
    case 'c':
    case 'g':
    case 't':
    case 'A':
    case 'C':
    case 'G':
    case 'T':
        return(true);
#ifdef DIPLOID
    case 'R':
        // G or A as puRine
    case 'Y':
        // T or C as pYrimidine
    case 'M':
        // aMino
    case 'K':
        // Keto
    case 'S':
        // Strong interaction
    case 'W':
        // Weak interaction
        return(true);
#endif
    default:
        return(false);
    }
}

inline int nt2Id(char nt)
{
    switch (nt) {
    case 'A':
    case 'a':
        return(0);
    case 'C':
    case 'c':
        return(1);
    case 'G':
    case 'g':
        return(2);
    case 'T':
    case 't':
        return(3);
    default:
        return(4);
    }
}

inline bool is0123(char nt)
{
    switch (nt) {
    case '0':
    case '1':
    case '2':
    case '3':
        return true;
    default:
        return false;
    }
}

inline
bool isNucleotide(char nt)
{
    switch (nt) {
    case 'a':
    case 'c':
    case 'g':
    case 't':
    case 'A':
    case 'C':
    case 'G':
    case 'T':
    case 'U':
    case 'u':
    case 'R':  // G or A as puRine
    case 'r':
    case 'Y':  // T or C as pYrimidine
    case 'y':
    case 'M':  // aMino
    case 'm':
    case 'N':  // unknown
    case 'n':
    case 'K':  // Keto
    case 'k':
    case 'S':  // Strong interaction
    case 's':
    case 'W':  // Weak interaction
    case 'w':
    case 'B':  // GTC
    case 'b':
    case 'D':  // GAT
    case 'd':
    case 'H':  // ACT
    case 'h':
    case 'V':  // GCA
    case 'v':
        return(true);
    default:
        return(false);
    }

}


/* Perform the WildCard comparison between two base. If match return true */
inline bool diNtWildCardComp(char nt1, char nt2)
{
    if (nt1 == nt2)
        return true;
    switch (nt1) {
    case 'R':
        if (nt2 == 'G' || nt2 == 'A' || nt2 == 'R')
            return true;
        break;
    case 'Y':
        if (nt2 == 'T' || nt2 == 'C' || nt2 == 'Y')
            return true;
        break;
    case 'M':
        if (nt2 == 'A' || nt2 == 'C' || nt2 == 'M')
            return true;
        break;
    case 'K':
        if (nt2 == 'G' || nt2 == 'T' || nt2 == 'K')
            return true;
        break;
    case 'S':
        if (nt2 == 'G' || nt2 == 'C' || nt2 == 'S')
            return true;
        break;
    case 'W':
        if (nt2 == 'T' || nt2 == 'A' || nt2 == 'W')
            return true;
        break;
    default:
        return false;
    }
    return false;
}
unsigned int diNtStrWildCardComp(char* read1, char* read2, unsigned int readlength);
unsigned int strComp(char* str1, char* str2, int l);
unsigned int strCompMarkDiff(char* str1, char* str2);

inline char complimentBase(char ntbase)
{
    switch (ntbase) {
    case 'a':
        return('t');
    case 'c':
        return('g');
    case 'g':
        return('c');
    case 't':
        return('a');
    case 'A':
        return('T');
    case 'C':
        return('G');
    case 'G':
        return('C');
    case 'T':
        return('A');
    default:
        return('N');
    }
}

inline char base2color(char nt, char color)
{
    switch (color) {
    case '1':
        switch (color) {
        case 'A':
            return('C');
        case 'C':
            return('A');
        case 'G':
            return('T');
        case 'T':
            return('G');
        default:
            return(nt);
        }
    case '2':
        switch (color) {
        case 'A':
            return('G');
        case 'C':
            return('T');
        case 'G':
            return('A');
        case 'T':
            return('C');
        default:
            return(nt);
        }
    case '3':
        switch (color) {
        case 'A':
            return('T');
        case 'C':
            return('G');
        case 'G':
            return('C');
        case 'T':
            return('A');
        default:
            return(nt);
        }
    default:  // include color 0
        return(nt);
    }
}

char getBaseFromColors(char nt, const char* colors, int pos);
void toUpperCase(char* caArray, int length);
void mutateBase(char* Base);
char* mutateRead(char* Kmer , unsigned int No_of_mutation);
char* mutatePairsOfConsecutiveBases(char* Kmer, unsigned int no_of_mutated_pairs);
bool isBadRead(const char* tkmer, unsigned int KmerLength);
bool isBadSOLiDRead(const char* Read, unsigned int ReadLength);
bool isBadRead(bool isSOLiD, const char* Read, unsigned int ReadLength);
//return the complement kmer from 5'->3', destroy the original kmer
char* reverseComplementKmer(char* Kmer);
char* reverseKmer(char* Kmer);
#endif


