const through = require("through2"),
    gutil = require("gulp-util"),
    fs = require("fs"),
    Path = require("path"),
    PluginError = gutil.PluginError;

// Plugin Constants
const PLUGIN_NAME = "gulp-scss-merge";
// RegExp to get the import path
const IMPORTS_REGEX = /^(?:@(?:\bimport\b).)(?:[\"|\'](.*)[\"|\'])(?:\;)/gm;
let allFileKeys = {};

/**
 * Take a stream and resolve all the scss imports based on its own path
 *
 * @param {string} [fileName] - Name of the output file
 *
 * @return {stream} Stream with all the @imports resolved
 */
function gulpScssMerge(fileName, basePath) {
    /**
     * Synchronous function that returns the content of a file
     *
     * @param {string} filePath - Path to a file
     *
     * @returns {string} The content of the file
     */
    function getFileContent(filePath) {
        // I need more tests to read the file Asynchronously
        // it break some @imports on our setup.
        console.log("-------------------", filePath);
        if (!fs.existsSync(filePath)) {
            console.log(filePath);
            if (filePath.indexOf("~") > -1) {
                filePath = filePath.replace("~", basePath);
            }
            if (!fs.existsSync(filePath)) {
                filePath =
                    filePath.substr(0, filePath.lastIndexOf("\\") + 1) +
                    "_" +
                    filePath.substr(filePath.lastIndexOf("\\") + 1, filePath.length);
            }
        }

        let result = "";
        if (allFileKeys[filePath]) {
        } else {
            allFileKeys[filePath] = 1;
            var content = fs.readFileSync(filePath, "utf8");
            if (content.indexOf("@import") >= 0) {
                content = getImports(content, filePath);
            }
            result = content;
        }

        return result;
    }

    /**
     * Return the absolute url of a scssImport based on
     * the parent path and the @import line on the parent
     *
     * @param {string} scssImport - The import declaration on the scss file
     * @param {string} path - Path of the file that contains the @import
     *
     * @returns {string} Path to the @import
     */
    function getImportPath(scssImport, path) {
        // If the input path comes also with a file name
        // take only the directory
        path = path.trim();
        path = Path.parse(path).ext === ".scss" ? Path.parse(path).dir : path;

        // Join the path to the parent file with the dirname
        // of the import and the resolved filename (with .scss)
        return Path.parse(scssImport).ext === ".scss"
            ? Path.join(path, Path.dirname(scssImport.trim()), Path.basename(scssImport))
            : Path.join(path, Path.dirname(scssImport.trim()), Path.basename(scssImport) + ".scss");
    }

    /**
     * Takes a content with @import's and replace it with the content of the
     * import
     *
     * @param {string} content - Scss file content with or without @imports
     * @param {string} filePath - Path to the file containing the @imports
     *
     * @returns {string} The content string with the resolved @imports
     */
    function getImports(content, filePath) {
        // Match all the @imports in the content param
        var match = IMPORTS_REGEX.exec(content);

        var imports = [];
        // Walk through all RegExp matches and store groups
        // in the imports array
        while (match != null) {
            imports.push({
                lineContent: match[0],
                filePath: getImportPath(match[1], filePath)
            });

            match = IMPORTS_REGEX.exec(content);
        }

        // For each @import found replace the @import line
        // with the resolved @import content
        imports.forEach(function(line) {
            content = content.replace(line.lineContent, getFileContent(line.filePath));
        });

        return content;
    }

    // Creating a stream through which each file will pass
    return through.obj(function(file, enc, cb) {
        if (file.isNull()) {
            // return empty file
            return cb(null, file);
        }
        if (file.isBuffer()) {
            file.contents = new Buffer(getImports(file.contents.toString(), file.base));
            file.path = Path.join(Path.dirname(file.path), fileName);
        }
        if (file.isStream()) {
            // I need to test streams to make sure that it works.
            throw new PluginError(PLUGIN_NAME, "Streams not supported");
        }

        cb(null, file);
    });
}

module.exports = gulpScssMerge;
