    /**
     * Copyright (c) 2015, Jozef Stefan Institute, Quintelligence d.o.o. and contributors
     * All rights reserved.
     *
     * This source code is licensed under the FreeBSD license found in the
     * LICENSE file in the root directory of this source tree.
     */
    /**
    * File-system module.
    * @module fs
    * @example
    * // import module
    * var fs = require('qminer').fs;
    * // open file in write mode
    * var fout = fs.openWrite('file.txt');
    * // write sync and close
    * fout.writeLine('example text');
    * fout.close();
    * // open file in read mode
    * var fin = fs.openRead('file.txt');
    * // read a line
    * var str = fin.readLine();
    */
    /**
        * Open file in read mode and return file input stream.
        * @param {string} fileName - File name.
        * @returns {module:fs.FIn} Input stream.
        * @example
        * // import fs module
        * var fs = require('qminer').fs;
        * // open file to write
        * var fout = fs.openWrite('read_text.txt');
        * // write to file
        * fout.write('This is awesome!');
        * // close the stream
        * fout.close();
        * // open file to read
        * var fin = fs.openRead('read_text.txt');
        */
     exports.openRead = function(fileName) { return Object.create(require('qminer').fs.FIn.prototype); }
    /**
        * Open file in write mode and return file output stream.
        * @param {string} fileName - File name.
        * @returns {module:fs.FOut} Output stream.
        * @example
        * // import fs module
        * var fs = require('qminer').fs;
        * // open file to write
        * var fout = fs.openWrite('write_text.txt');
        * // close the stream
        * fout.close();
        */
     exports.openWrite = function(fileName) { return Object.create(require('qminer').fs.FOut.prototype); }
    /**
        * Open file in append mode and return file output stream.
        * @param {string} fileName - File name.
        * @returns {module:fs.FOut} Output stream.
        * @example
        * // import fs module
        * var fs = require('qminer').fs;
        * // open file to write
        * var fout = fs.openWrite('append_text.txt');
        * // close the stream
        * fout.close();
        * // open file in append mode
        * var foutAppend = fs.openAppend('append_text.txt');
        * // close the stream
        * foutAppend.close();
        */
     exports.openAppend = function(fileName) { return Object.create(require('qminer').fs.FOut.prototype); }
    /**
        * Checks if the file exists.
        * @param {string} fileName - File name.
        * @returns {boolean} True if file exists.
        * @example
        * // import fs module
        * var fs = require('qminer').fs;
        * // check if a file exists
        * fs.exists('text.txt');
        */
     exports.exists = function(fileName) { return false; }
    /**
        * Copies a file.
        * @param {string} source - Source file name.
        * @param {string} dest - Destination file name.
        * @example
        * // import fs module
        * var fs = require('qminer').fs;
        * // open file to write
        * var fout = fs.openWrite('text.txt');
        * // close the stream
        * fout.close();
        * // copy the file
        * // var destination = fs.copy('text.txt', 'copy.txt');
        */
     exports.copy = function(source, dest) { return ""; }
    /**
        * Moves a file.
        * @param {string} source - Source file name.
        * @param {string} dest - Destination file name.
        * @example
        * // import fs module
        * var fs = require('qminer').fs;
        * // open file to write
        * var fout = fs.openWrite('text.txt');
        * // close the stream
        * fout.close();
        * // move the file
        * // var destination = fs.move('text.txt', 'move.txt');
        */
     exports.move = function(source, dest) { return ""; }
    /**
        * Deletes a file.
        * @param {string} fileName - File name.
        * @returns {boolean} True if delete succeeded.
        * @example
        * // import fs module
        * var fs = require('qminer').fs;
        * // open file to write
        * var fout = fs.openWrite('delete.txt');
        * // close the stream
        * fout.close();
        * // delete the file
        * var destination = fs.del('delete.txt');
        */
     exports.del = function(fileName) { return false; }
    /**
        * Renames a file.
        * @param {string} source - Source file name.
        * @param {string} dest - Destination file name.
        * @example
        * // import fs module
        * var fs = require('qminer').fs;
        * // open file to write
        * var fout = fs.openWrite('text.txt');
        * // close the stream
        * fout.close();
        * // rename the file
        * if (fs.exists('rename.txt')) {
        *    fs.del('rename.txt');
        * }
        * var destination = fs.rename('text.txt', 'rename.txt');
        */
     exports.rename = function(source, dest) { return ""; }
    /**
        * @typedef {Object} FileInfo
        * Information about the file.
        * @property  {string} createTime - Create time.
        * @property  {string} lastAccessTime - Last access time.
        * @property  {string} lastWriteTime - Last write time.
        * @property  {number} size - File size in bytes.
        */
    /**
        * Returns the file info.
        * @param {string} fileName - File name.
        * @returns {module:fs~FileInfo} File info object.
        * @example
        * // import fs module
        * var fs = require('qminer').fs;
        * // open file to write
        * var fout = fs.openWrite('text.txt');
        * // close the stream
        * fout.close();
        * // get the file info
        * var info = fs.fileInfo('text.txt');
        */
     exports.fileInfo = function(fileName) { return { createTime : "",  lastAccessTime: "", lastWriteTime: "", size: 0 }}
    /**
        * Creates a folder.
        * @param {string} dirName - Folder name.
        * @returns {boolean} True if succeeded.
        * @example
        // import fs module
        * var fs = require('qminer').fs;
        * // create a folder
        * var makeFolder = fs.mkdir('folder');
        */
     exports.mkdir = function(dirName) { return false; }
    /**
        * Removes a folder.
        * @param {string} dirName - Folder name.
        * @returns {boolean} True if succeeded.
        * @example
        // import fs module
        * var fs = require('qminer').fs;
        * // create a folder
        * var makeFolder = fs.mkdir('folder');
        * // delete folder
        * if (makeFolder) {
        *    fs.rmdir('folder');
        * }
        */
     exports.rmdir = function(dirName) { return false; }
    /**
        * Returns a list fo files in the folder.
        * @param {string} dirName - Folder name.
        * @param {string} [fileExtension] - Results are filtered by file extension.
        * @param {boolean} [recursive=false] - Recursively searches for file names if true.
        * @returns {Array.&lt;string>} Array of file names.
        * @example
        * // import fs module
        * var fs = require('qminer').fs;
        * // get the names of all files
        * var fileNames = fs.listFile('./');
        */
     exports.listFile = function(dirName, fileExtension, recursive) { return ['']; }
    /**
         * Reads a buffer line by line and calls a callback for each line.
         * @param {String | module:fs.FIn | Buffer} buffer - Name of the file, input stream of a Node.js buffer.
         * @param {function} onLine(line) - A callback that gets called on each line (for example: `function (line) {}`).
         *   Function must return `true` to continue reading, else reading is stoped and `onEnd` is called.
         * @param {function} onEnd(err) - A callback that gets returned after all the lines have been read or
         *   function `onLine` returned `false`. If error was due to exception, the exception is provided in `err`.
         * @example
         * // import fs module
         * var fs = require('qminer').fs;
         * // create a file and write some lines
         * var fout = fs.openWrite('poem.txt');
         * fout.write('I dig,\nYou dig,\nHe digs,\nShe digs,\nWe dig,\nThey dig.\n It\'s not a beautiful poem, but it\'s deep.');
         * fout.close();
         * // open the file in read mode
         * var fin = fs.openRead('poem.txt');
         * // read the file line by line and call functions
         * var numberOfLines = 0;
         * function onLine(line) {
         *     console.log(line);
         *     numberOfLines += 1;
         *     return true;
         * }
         * function onEnd(err) {
         *     if (err) { console.log("Error:", err); }
         *     console.log("Number of lines", numberOfLines);
         * }
         * fs.readLines(fin, onLine, onEnd);
         */
     exports.readLines = function (buffer, onLine, onEnd) {}
    /**
        * Input file stream.
        * @classdesc Used for reading files.
        * @class
        * @param {string} fileName - File name.
        * @example
        * // import module
        * var fs = require('qminer').fs;
        * // open file in write mode
        * var fout = fs.openWrite('file.txt');
        * // write sync and close
        * fout.writeLine('example text');
        * fout.close();
        * // open file in read mode
        * var fin = new fs.FIn('file.txt');
        * // read a line
        * var str = fin.readLine();
        */
     exports.FIn = function(fileName) { return Object.create(require('qminer').fs.FIn.prototype); }
    /**
        * Peeks a character.
        * @returns {string} Character string.
        * @example
        * // import module
        * var fs = require('qminer').fs;
        * // open file in write mode
        * var fout = fs.openWrite('file.txt');
        * // write sync and close
        * fout.writeLine('example text');
        * fout.close();
        * // open file in read mode
        * var fin = new fs.FIn('file.txt');
        * // peek the next character
        * var char = fin.peekCh();
        */
     exports.FIn.prototype.peekCh= function() { return ''; }
    /**
        * Reads a character.
        * @returns {string} Character string.
        * @example
        * // import module
        * var fs = require('qminer').fs;
        * // open file in write mode
        * var fout = fs.openWrite('file.txt');
        * // write sync and close
        * fout.writeLine('example text');
        * fout.close();
        * // open file in read mode
        * var fin = new fs.FIn('file.txt');
        * // get the next character
        * var char = fin.getCh();
        */
     exports.FIn.prototype.getCh= function() { return ''; }
    /**
        * Reads a line.
        * @returns {string} Line string.
        * @example
        * // import module
        * var fs = require('qminer').fs;
        * // open file in write mode
        * var fout = fs.openWrite('file.txt');
        * // write sync and close
        * fout.writeLine('example text');
        * fout.close();
        * // open file in read mode
        * var fin = new fs.FIn('file.txt');
        * // get/read a new line
        * var line = fin.readLine();
        */
     exports.FIn.prototype.readLine = function() { return ''; }
    /**
        * Reads a string that was serialized using `fs.FOut.writeBinary`.
        * @returns {string} String.
        * @example
        * // import fs module
        * var fs = require('qminer').fs;
        * // read a string that was serialized using fs.FOut.writeBinary
        */
     exports.FIn.prototype.readString = function() { return ''; }
    /**
        * True if end of file is detected. Otherwise, false. Type `boolean`.
        * @example
        * // import module
        * var fs = require('qminer').fs;
        * // open file in write mode
        * var fout = fs.openWrite('file.txt');
        * // write sync and close
        * fout.writeLine('example text');
        * fout.close();
        * // open file in read mode
        * var fin = new fs.FIn('file.txt');
        * // check if it's end of the file
        * var eof = fin.eof;
        */
     exports.FIn.prototype.eof = false;
    /**
        * Length of input stream. Type `number`.
        * @example
        * // import module
        * var fs = require('qminer').fs;
        * // open file in write mode
        * var fout = fs.openWrite('file.txt');
        * // write sync and close
        * fout.writeLine('example text');
        * fout.close();
        * // open file in read mode
        * var fin = new fs.FIn('file.txt');
        * // get the length of the document
        * var len = fin.length;
        */
     exports.FIn.prototype.length = 0;
    /**
        * Reads the whole stream.
        * @returns {string} Content of the file.
        * @example
        * // import module
        * var fs = require('qminer').fs;
        * // open file in write mode
        * var fout = fs.openWrite('file.txt');
        * // write sync and close
        * fout.writeLine('example text');
        * fout.close();
        * // open file in read mode
        * var fin = new fs.FIn('file.txt');
        * // get/read a the whole string
        * var all = fin.readAll();
        */
     exports.FIn.prototype.readAll = function() { return ''; }
    /**
        * Closes the input stream.
        * @example
        * // import module
        * var fs = require('qminer').fs;
        * // open file in write mode
        * var fout = fs.openWrite('file.txt');
        * // write sync and close
        * fout.writeLine('example text');
        * fout.close();
        * // open file in read mode
        * var fin = new fs.FIn('file.txt');
        * // close the stream
        * fin.close();
        */
     exports.FIn.prototype.close = function() { }
    /**
        * Checks if the input stream is closed.
        * @example
        * // import module
        * var fs = require('qminer').fs;
        * // open file in write mode
        * var fout = fs.openWrite('file.txt');
        * // write sync and close
        * fout.writeLine('example text');
        * fout.close();
        * // open file in read mode
        * var fin = new fs.FIn('file.txt');
        * // check if the stream is closed
        * var check = fin.isClosed();
        */
     exports.FIn.prototype.isClosed = function() { return false; }
    /**
        * Output file stream.
        * @classdesc Used for writing files.
        * @class
        * @param {String} fileName - File name.
        * @param {boolean} [append=false] - Append flag.
        * @example
        * // import module
        * var fs = require('qminer').fs;
        * // open file in write mode
        * var fout = new fs.FOut('file.txt');
        * // write a line
        * fout.writeLine('example text');
        * // close
        * fout.close();
        */
     exports.FOut = function(fileName, append) {}
    /**
        * Writes a string or number or a JSON object in human readable form.
        * @param {(String | Number | Object)} arg - Argument to write.
        * @returns {module:fs.FOut} Self.
        * @example
        * // import module
        * var fs = require('qminer').fs;
        * // open file in write mode
        * var fout = new fs.FOut('file.txt');
        * // write a string
        * fout.write('example text');
        * // close
        * fout.close();
        */
     exports.FOut.prototype.write = function(arg) { return this; }
    /**
        * Writes a string or number or a JSON object in binary form.
        * @param {(String | Number | Object)} str - Argument to write.
        * @returns {module:fs.FOut} Self.
        * @example
        * // import fs module
        * var fs = require('qminer').fs;
        * // save a string in binary form
        */
     exports.FOut.prototype.writeBinary = function(arg) { return this; }
    /**
        * Writes a string and adds a new line.
        * @param {String} str - String to write.
        * @returns {module:fs.FOut} Self.
        * @example
        * // import module
        * var fs = require('qminer').fs;
        * // open file in write mode
        * var fout = new fs.FOut('file.txt');
        * // write a line
        * fout.writeLine('example text');
        * // close
        * fout.close();
        */
     exports.FOut.prototype.writeLine = function(str) { return this; }
    /**
        * Flushes the output stream.
        * @returns {module:fs.FOut} Self.
        * @example
        * // import module
        * var fs = require('qminer').fs;
        * // open file in write mode
        * var fout = new fs.FOut('file.txt');
        * // write a line
        * fout.writeLine('example text');
        * // flush the stream
        * fout.flush();
        * // close
        * fout.close();
        */
     exports.FOut.prototype.flush = function() { return this; }
    /**
        * Closes the output stream.
        * @example
        * // import module
        * var fs = require('qminer').fs;
        * // open file in write mode
        * var fout = new fs.FOut('file.txt');
        * // write a line
        * fout.writeLine('example text');
        * // close
        * fout.close();
        */
     exports.FOut.prototype.close = function() {}

        function processCsvLine(opts) {
        	if (opts.delimiter == null) opts.delimiter = ',';
        	if (opts.onLine == null) throw 'Line callback missing!';
        	if (opts.onEnd == null) opts.onEnd = function () {}
        	if (opts.lineLimit == null) opts.lineLimit = Infinity;
        	if (opts.skipLines == null) opts.skipLines = 0;
        	if (opts.quote == null) opts.quote = '"';

        	var strDelimiter = opts.delimiter;

        	var lineCb = opts.onLine;

        	// Create a regular expression to parse the CSV values.
            var objPattern = new RegExp((
                    // Delimiters.
                    "(\\" + strDelimiter + "|\\r?\\n|\\r|^)" +
                    // Quoted fields.
                    "(?:\"([^\"]*(?:\"\"[^\"]*)*)\"|" +
                    // Standard fields.
                    "([^\"\\" + strDelimiter + "\\r\\n]*))"
                ), "gi");

            var quoteRegex = new RegExp(opts.quote, 'g');

            var i = 0;
        	var line = '';

        	return function (batch) {
        		line += batch;

        		// if the number of delimiters is odd => the line hasn't ended, but a string field contained a line ending
        		if ((line.match(quoteRegex) || []).length % 2 == 1) {
        			return true;
        		}

    			try {
    				var arrData = [ ];
    	            // Create an array to hold our individual pattern matching groups.
    	            var arrMatches = null;
    	            // Keep looping over the regular expression matches until we can no longer find a match.
    	            while (arrMatches = objPattern.exec(line)){
    	                // Let's check to see which kind of value we captured (quoted or unquoted).
    	                var strMatchedValue = arrMatches[2] ?
    	                    // We found a quoted value. When we capture this value, unescape any double quotes.
    	                    arrMatches[2].replace(new RegExp( "\"\"", "g" ), "\"") :
    	                    // We found a non-quoted value.
    	                    arrMatches[3];
    	                // Now that we have our value string, let's add it to the data array.
    	                arrData.push(strMatchedValue);
    	            }

    	            i++;
    	            line = '';

    	            // Return the parsed data.
    	            if (i > opts.skipLines) {
    	            	lineCb(arrData);
    	            }

    	            return ++i &lt; opts.lineLimit;
    			} catch (e) {
    				opts.onEnd(e);
    				return false;	// stop the loop if an error occurs
    			}
        	}
        }

        /**
         * Reads a buffer, containing a CSV file, line by line and calls a callback for each line.
         * As specified in CSV format standard defined in [RFC 4180]{@link https://tools.ietf.org/html/rfc4180}
         * double-quotes (") can be used as escape characters. If a double-quote appears in a field, the field nust be
         * enclosed in double-quotes and the double-quote appearing inside a field must be escaped by preceding it with
         * another double quote.
         * The callback function accepts an array with the values of the current line.
         * @param {Buffer} buffer - The Node.js buffer.
         * @param {Object} opts - Options parameter.
         * @param {function} opts.onLine - A callback that gets called on each line (for example: `function (lineArr) {}`).
         * @param {function} opts.onEnd - A callback that gets returned after all the lines have been read.
         * @param {String} opts.delimiter - The delimiter used when parsing.
         * @param {Number} opts.lineLimit - The maximum number of lines read.
         * @param {Number} opts.skipLines - The number of lines that should be skipped before first calling the callback.
         * @example
         * // import fs module
         * let fs = require('qminer').fs;
         * // create a file and write some lines
         * let fout = fs.openWrite('test.csv');
         * fout.write('name,movie\nGeorge Clooney,"O Brother, Where Art Thou?"\n"Sylvester ""Sly"" Stallone",Expendables');
         * fout.close();
         * // open the file in read mode
         * let fin = fs.openRead('test.csv');
         * // prepare callbacks for csv parsing
         * // count the lines and for each line output the parsed cells
         * let nLines = 0;
         * function onLine(lineVals) {
         *     nLines += 1;
         *     console.log(lineVals);
         *     return true;
         * }
         * // at the end output the number of lines
         * function onEnd(err) {
         *     if (err) { console.log("Error:", err); }
         *     console.log("Number of lines", nLines);
         * }
         * // parse the csv files
         * fs.readCsvLines(fin, {
         *     "onLine": onLine,
         *     "onEnd": onEnd
         * });
         */
        exports.readCsvLines = function (fin, opts) {
        	exports.readLines(fin, processCsvLine(opts), opts.onEnd);
        }

        /**
         * Reads json that was serialized using `fs.FOut.writeJson`.
         * @returns {Object} Json object.
         * @example
         * // import fs module
         * var fs = require('qminer').fs;
         * // create and save a json and then read it using the readJson method
         */
        exports.FIn.prototype.readJson = function () {
        	var str = this.readString();
        	return JSON.parse(str);
        }

        /**
         * Saves json object, which can be read by `fs.FIn.readJson`.
         * @returns {Object} obj - Json object to write.
         * @returns {module:fs.FOut} Self.
         * @example
         * // import fs module
         * var fs = require('qminer').fs;
         * // create and save a json using the writeJson method
         */
        exports.FOut.prototype.writeJson = function (json) {
        	var str = JSON.stringify(json);
        	this.writeBinary(str);
        	return this;
        }