#include "Filename.h"

inline char* myStrCpy(char* caBuf, const char* str, int iBufSize)
{
    int iBufSizeMinus1 = iBufSize - 1;
    char* returnV = strncpy(caBuf, str, iBufSizeMinus1);
    caBuf[iBufSizeMinus1] = '\0';
    return(returnV);
}

/*
 * Get the filename from the next line of a file list.
 * If there are no more files, return "\0"
 */
bool GetNextFilenameFromListFile(ifstream &ifile, char* filenameBuffer)
{
    // test file object to see if the filename we get is correct
    ifstream testfile;
    if (ifile.good()) {
        do {
            ifile.getline(filenameBuffer, MAX_FILE_PATH);
            if (filenameBuffer[0] != '\0' && filenameBuffer[0] != EOF) {
                if (filenameBuffer[0] == '#') // # follows by comments
                    continue;
                testfile.open(filenameBuffer);
                if (!testfile.good()) {
                    cout << filenameBuffer << " doesn't exist or permission deny!!" << endl;
                    testfile.close();
                    continue; //get next file name
                } else {
                    testfile.close();
                    break;
                }
            } else if (ifile.eof())	{
                ifile.close();
                filenameBuffer[0] = '\0';
                return(false);
            }
        } while (strcmp(filenameBuffer, "") == 0 || filenameBuffer[0] == '#');
    } else {
        return(false);
    }
    return(true);
}

bool GetNextFilenamePairFromListFile(ifstream &ifile, char* filenameBuffer1, char* filenameBuffer2)
{
    ifstream testfile1;
    ifstream testfile2;
    bool getValidFilePair = false;
    filenameBuffer1[0] = '\0';
    filenameBuffer2[0] = '\0';

    if (ifile.good()) {
        do {
            char filenameBuffer[FILENAME_MAX];
            ifile.getline(filenameBuffer, MAX_FILE_PATH);
            if (filenameBuffer[0] != '\0' && filenameBuffer[0] != EOF) {
                if (filenameBuffer[0] != '#') { // Not a comment
                    char* pch = strtok(filenameBuffer, "\t, ");
                    if (pch != NULL)
                        strcpy(filenameBuffer1, pch);
                    pch = strtok(NULL, "\t, ");
                    if (pch != NULL)
                        strcpy(filenameBuffer2, pch);
                    if (filenameBuffer1[0] != '\0' && filenameBuffer2[0] != '\0') {
                        if (!fileExist(filenameBuffer1)) {
                            cout << filenameBuffer1 << " doesn't exist !!" << endl;
                            filenameBuffer1[0] = '\0';
                        } else if (!fileExist(filenameBuffer2)) {
                            cout << filenameBuffer2 << " doesn't exist !!" << endl;
                            filenameBuffer2[0] = '\0';
                        } else {
                            getValidFilePair = true;
                        }
                    }
                }
            }
            if (ifile.eof()) {
                ifile.close();
                break;
            }
        } while (!getValidFilePair);
    } else {
        cout << "Can't get new file" << endl;
    }
    return(getValidFilePair);
}

bool GetNextFilenamePairFromListFile(const char* filename, char* filenameBuffer1, char* filenameBuffer2) {
	ifstream readsFileList(filename);
	if(readsFileList.bad()) {
		return(false);
	}
	bool bMatePairedReads = GetNextFilenamePairFromListFile(readsFileList, filenameBuffer1, filenameBuffer2);	
    readsFileList.close();
	return(bMatePairedReads);
}

int chExtName(char* filename, const char* Extname)
{
    int i = 0;
    //Give Ext name starts with '.'

    if (filename != NULL && Extname != NULL) {
        for (i = (int)strlen(filename); i > 0; i--) {
            if (filename[i] == '.')
                break;
        }
        if (i > 0)
            strcpy(&(filename[i]), Extname);
        else {
            //no extended filename
            int l = (int)strlen(filename);
            strcpy(&(filename[l]), Extname);
            //concatenate the Extended file at the end
        }
        return((int)strlen(filename));
    }
    return(-1);
}

string chExtName(string filename, string Extname)
{
    char fileNameBuf[FILENAME_MAX];
    myStrCpy(fileNameBuf, filename.c_str(), FILENAME_MAX);
    chExtName(fileNameBuf, Extname.c_str());
    return(string(fileNameBuf));
}

char* addPath(const char* filename, const char* directory, char* path)
{
    char tmpbuffer[MAX_FILE_PATH];
    myStrCpy(tmpbuffer, filename, MAX_FILE_PATH);
    //in case path and filename or the same buffer
    sprintf(path, "%s//%s", directory, tmpbuffer);
    return(path);
}

string getFullPath(string directory, string filename)
{
#if defined WIN32 || defined WIN64
    string fullPath = directory.append("\\").append(filename);
#else
    string fullPath = directory.append("/").append(filename);
#endif
    return(fullPath);
}

// return the pointer to the start of a file name, given a path
const char* getPtrBasename(const char* Path)
{
    int i = 0;
    for (i = (int)strlen(Path) - 1; i >= 0; i--) {
        char c = Path[i];
        if (isspace(c) ||
                iscntrl(c) ||\
                (c == '<') ||\
                (c == '>') ||\
                (c == ':') ||\
                (c == '"') ||\
                (c == '|') ||\
                (c == '?') ||\
                (c == '*') ||\
                (c == '%') ||\
                (c == '/') ||\
                (c == '\\'))

        {
            break; // if not alpha, digit, '_', '.' or space
        }
    }
    return(&Path[i + 1]);
}

// get the file name from the path without extended file name like .txt
int getBasename(const char* Path, char* fileNameWithoutExt)
{
    // i and j are the start and end of the filename in the path.
    int j = 0;
    if (Path != NULL && fileNameWithoutExt != NULL) {
        const char* fileName = getPtrBasename(Path);
        for (j = (int)strlen(fileName); j >= 0; j--) {
            if (fileName[j] == '.')
                break;
        } // get the start position of ext file
        strcpy(fileNameWithoutExt, fileName);
        // if there is no ext name
        if (j > 0) {
            fileNameWithoutExt[j] = '\0';
        }
    }
    return((int)strlen(fileNameWithoutExt));
}

string getBasename(const char* Path)
{
    char fileNameWithoutExt[FILENAME_MAX];
    getBasename(Path, fileNameWithoutExt);
    return(string(fileNameWithoutExt));
}

//Get the name from the path and store in Title
//removed the number at the end of the Filename
int getTitleFromPath(char* Path, char* Title)
{
    int i = 0;
    getBasename(Path, Title);

    for (i = (int)strlen(Title); i > 0; i--) {
        if (Title[i] == '_') {
            if (atoi(&(Title[i+1])) > 0) {
                //remove the '_' and every number after it
                for (; Title[i] == '_'; i--)
                    Title[i] = '\0';
            }
            return(0);
        }
    }
    return(0);
}

const char* getExtName(const char* filename)
{
    // Return the char pointer point to the postfix of the char array
    // Ex: given a.b.txt return const char* ".txt"
    // Ex: given abc return const char* "abc"
    int i = 0;
    for (i = (int)strlen(filename); i > 0; i--) {
        if (filename[i] == '.')
            break;
    }
    return(&(filename[i]));
}

bool hasTheExtName(const char* filename, const char* extName)
{
    const char* realExtName = getExtName(filename);
    int  i;
    for (i = 0; extName[i] != '\0' && realExtName[i] != '\0'; i++) {
        if (tolower(extName[i]) != tolower(realExtName[i]))
            return(false);
    }
    if (i == 0) { //No ExtName
        return (false);
    } else {
        return(extName[i] ==  realExtName[i]); // one may be the prefix of the other
    }
}

bool fileExist(const char* filename)
{
    if (filename != NULL && filename[0] != 0) {
        ifstream iFile;
        iFile.open(filename, ifstream::in);
        // iFile.close();
        if (iFile.fail()) {
            return(false); // not exist
        } else {
            iFile.close();
            return (true); //exist;
        }
    }
    return(false); // wrong file name
}

bool checkFileExist(const char* filename)
{
    if (!fileExist(filename)) {
        cout << filename << " dosent exist.\n" << endl;
        return(false);
    } else {
        return(true);
    }
}

void filenameLize(char* string)
{
    for (int i = 0; string[i] != '\0'; i++) {
        char c = string[i];
        if (!(isalnum(c) || c == '.')) {
            if (i == 0) { // If the first character is non_valid, replace to 'Z'
                strcpy(string, "NULL_Filename");
            } else { // Truncated the string if a space, tab or comma
                if (c == ' ' || c == '\t' || c == ',' || c == '\n' || c == '\r') {
                    string[i] = '\0';
                    break;
                } else { // else replace to '_'
                    string[i] = '_';
                }
            }
        }
    }
}

bool isPathWritable(const char* filename)
{
    FILE *fp = NULL;
    fp = fopen(filename, "w");
    if (fp == NULL) {
        return false;
    } else {
        fclose(fp);
        return true;
    }
}


bool checkPathCharsAreValid(const char* pathStr)
{
    // null path will return true
    for (int i = 0; pathStr[i] != '\0'; i++) {
        char c = pathStr[i];
        if (isspace(c) || iscntrl(c)) {
            return(false);
        }
        switch (c) {
        case '&':
        case '"':
        case '*':
        case '?':
        case ':':
        case '>':
        case '<':
        case '\'':
            return(false);
        default:
            break;
        }
    }
    return(true);
}

bool dirExist(const char* strFolderPath)
{
    if ( fileExist(strFolderPath)) {
        struct stat status;
        stat( strFolderPath, &status );
        if ( status.st_mode & S_IFDIR ) {
            return(true);
        }
    }
    return(false);
}
