#include <iostream>
#include <fstream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <string>
#include <string.h>

//#define DEBUG

using namespace std;

/// File type fpr function:readPath
typedef struct ftype {
	char** file_name; // File name array
	int line_cnt; // Return file counts of file_name
} ftype;

enum SelfFile {
	FILE_POS = 0,
	FILE_NEG = 1,
	FILE_NEG_HARD = 2
};

/// File class for ftype
class fileClass {

private:
	void initial();
	vector<int> file_num;  // File numbers for each fileArr
	vector<ftype> fileArr; // POS, NEG, HARD txt array

public:


	void loadFile(ftype src, SelfFile type);
	void loadFile(char* txtPath, SelfFile type);
	void loadFile(char* , char* );


	void setNum(int num, SelfFile type);
	int getNum(SelfFile type);
	char* getName(int num, SelfFile type);


	fileClass() {
		initial();
	}

	/* Two text path*/
	fileClass(char* pos_path, char* neg_path) {
		initial();
		loadFile(pos_path, FILE_POS);
		loadFile(neg_path, FILE_NEG);
	}

	/* Three text path*/
	fileClass(char* pos_path, char* neg_path, char* hard_path) {
		initial();
		loadFile(pos_path, FILE_POS);
		loadFile(neg_path, FILE_NEG);
		loadFile(hard_path, FILE_NEG_HARD);
	}

};

/// Read "file path" from File and convert into array
ftype readPath(char* filePath_in) {

	ftype fr;
	fr.line_cnt = 0;
    fr.file_name = NULL;

	char filePath[100];
	sprintf(filePath,"%s", filePath_in);

	FILE* fp = fopen(filePath, "r+");
	if (fp == NULL) {
		fprintf(stderr, "Error Reading File : %s\n", filePath);
	}
	else {
		fprintf(stderr,"Reading File : %s\n", filePath);
	}

	char tmp = 0;
	int s_cnt = 0;
	int pos = 0, pos_eof = 0;


	while (1) {
		if (feof(fp)) break;

		tmp = fgetc(fp);

		/// Replace '\' in the file
		if (tmp == '\\') {
			fseek(fp, ftell(fp) - 1, SEEK_SET);
			fputc('/', fp);
			fflush(fp);
		}

		/// Check how many lines(\n) in the file
		if (tmp == '\n') {
			if ((ftell(fp) - pos) == 2) // Sequential '/n'
				fprintf(stderr, "Warning : Sequential shift line on : %d\n", fr.line_cnt);;
			fr.line_cnt++;
			pos = ftell(fp);
		}
	}

#ifdef DEBUG
	printf("\nStep1..");
#endif

	/// Check exact line count
	fseek(fp, 0, SEEK_END);
	pos_eof = ftell(fp); // Last position of the file
	fr.line_cnt = (pos == pos_eof) ? fr.line_cnt : (fr.line_cnt + 1); // Check if last symbol is "\n"

	rewind(fp); // Return file pointer to start

#ifdef DEBUG
    printf("...[OK]\n");
    printf("Step2..");
#endif

	/// Allocate memory for file name pointer array (double pointer)

	//fr.file_name = (char**)malloc(sizeof(char*)*fr.line_cnt);
	fr.file_name = new char*[fr.line_cnt];

	int f_ret; // fscanf flag

	/// Scan file name into pointer array

#ifdef DEBUG
	printf("...[OK]\n");
	printf("Step3..");
#endif

	while (1) {
		if (feof(fp)) break;

		//fr.file_name[s_cnt] = (char*)malloc(sizeof(char) * 100);
		fr.file_name[s_cnt] = new char[100];
		f_ret = fscanf(fp, "%s", fr.file_name[s_cnt]);

		if (f_ret != 1)
			sprintf(fr.file_name[s_cnt], "Empty");

		s_cnt++;

	}

#ifdef DEBUG
    printf("...[OK]\n");
    printf("Step4..");
#endif

	/// Let other empty pointer array shows "Empty"
	for (int i = s_cnt; i<fr.line_cnt; i++) {
		//fr.file_name[i] = (char*)malloc(sizeof(char) * 100);
		fr.file_name[i] = new char[100];
		sprintf(fr.file_name[i], "Empty");
	}

#ifdef DEBUG
    printf("...[OK]\n");
#endif

	fclose(fp);

	return fr;
}

/* Initial FileClass */
void fileClass::initial(){

	/// Erase
	fileArr.clear();
	file_num.clear();

	/// Resize
	file_num.resize(3);
	fileArr.resize(3);
}


/* Load <ftype>file into <class>fileclass */
void fileClass::loadFile(ftype src, SelfFile type){

	fileArr.at(type) = src;
	file_num.at(type) = src.line_cnt;

}

/* Load <ftype>file into <class>fileclass by <char*>text path */
void fileClass::loadFile(char *txtPath, SelfFile type){

    printf("\nLoad Test: %s, type = %d\n",txtPath,type);
	fileArr.at(type) = readPath(txtPath);
	file_num.at(type) = fileArr.at(type).line_cnt;
    printf("Load Test [done]\n");
}


void fileClass::loadFile(char * posPath, char * negPath)
{
	loadFile(posPath, FILE_POS);
	loadFile(negPath, FILE_NEG);
}

/* Set load number amount for data
	/ int num : Only indicate a number, doensn't affect the actual data
*/
void fileClass::setNum(int num, SelfFile type){

	file_num.at(type) = num;
}

/* Get load number amount for data
	/  @return file_num : Only indicate a number, doensn't affect the actual data
*/
int fileClass::getNum(SelfFile type)
{
	return file_num.at(type);
}


void freeTest(ftype *test){
    for (int i =0; i<test->line_cnt;i++)
        delete test->file_name[i];
    delete test;
    //free(test);
}

void testResult(ftype test){

    for (int i=0; i < test.line_cnt; i++){
        printf("test[%d]=%s",i, test.file_name[i]);
    }


}
int main()
{
	fileClass dataset(

		"Path/train_Pos.txt",
		"Path/train_Neg_12180.txt",
		"Path/train_Neg_I.txt"
	);

	fileClass dataset2(

		"Path/train_Pos.txt",
		"Path/train_Neg_12180.txt",
		"Path/train_Neg_I.txt"
	);

	/*ftype test1 = readPath("Path/train_Pos.txt");
	ftype test2 = readPath("Path/train_Pos.txt");
	ftype test3 = readPath("Path/train_Pos.txt");
	ftype test4 = readPath("Path/train_Pos.txt");
	ftype test5 = readPath("Path/train_Pos.txt");
	ftype test6 = readPath("Path/train_Pos.txt");*/

    printf("\n\n\n[ALL DONE]\n");
	system("PAUSE");
    return 0;
}
