var npm = require("npm");
var fs = require('fs');
var path = require('path');
var os = require('os');
var PLATFORM = os.platform();

var REQUIRE_RE = /"(?:\\"|[^"])*"|'(?:\\'|[^'])*'|\/\*[\S\s]*?\*\/|\/(?:\\\/|[^/\r\n])+\/(?=[^\/])|\/\/.*|\.\s*require|(?:^|[^$])\brequire\s*\(\s*(["'])(.+?)\1\s*\)/g;
var IMPORT_RE = /"(?:\\"|[^""])*"|'(?:\\'|[^''])*'|\/\*[\S\s]*?\*\/|\/(?:\\\/|[^/\r\n])+\/(?=[^\/])|\/\/.*|\.\s*@import|(?:^|[^$])@import\s*(["''"])(.+?)\1\s*;/g;
var SLASH_RE = /\\\\/g;

var packageFile = "../package.json";
var requireList = [];
var depsJS = {};
var depsCSS = {};
var depsModules = {};
var processFolder = [];
var mainEntry = path.resolve(__dirname, path.dirname(packageFile));

resolveModules(packageFile);
contentToCMD();

function contentToCMD() {

    var allContent = "";

    requireList.forEach(function (item) {
        var extName = path.extname(item);
        var temptFile = item + ".tempt";
        var content;
        var hasTemptFile = false;
        if (fs.existsSync(temptFile)) {
            hasTemptFile = true;
            content = fs.readFileSync(temptFile, 'utf-8');
        } else {
            content = fs.readFileSync(item, 'utf-8');
        }

        var moduleId = item.replace(mainEntry + '/', '');
        if (extName === '.html') {
            content = jsEscape(content);
            allContent += "define('" + moduleId + "', function (require, exports, module) {\n return ' " + content + "';});\n";
        } else {
            allContent += 'define("' + moduleId + '", function (require, exports, module) {\n' + content + '\n});\n\n';
        }

        if (hasTemptFile) {
            fs.unlinkSync(temptFile);
        }
    });
    fs.writeFile('result.js', allContent, function () {});
}

function jsEscape(content) {
        return content.replace(/(['\\])/g, '\\$1')
            .replace(/[\f]/g, '\\f')
            .replace(/[\b]/g, '\\b')
            .replace(/[\n]/g, '\\n')
            .replace(/[\t]/g, '\\t')
            .replace(/[\r]/g, '\\r')
            .replace(/[\u2028]/g, '\\u2028')
            .replace(/[\u2029]/g, '\\u2029');
}

function resolveModules(packageFile) {
    var packageFolder = path.resolve(__dirname, path.dirname(packageFile));
    var packageJSON = require(packageFile);

    //将执行环境，转变到package.json所在的文件夹,并压入路径堆栈中
    process.chdir(packageFolder);
    processFolder.push(packageFolder);

    var mainJSFile = packageJSON.main || path.join(packageFolder, "index.js");
    var mainCSSFile = packageJSON.mainCss || path.join(packageFolder, "index.scss");

    if (!depsJS[path.resolve(mainJSFile)]) {
        depsJS[path.resolve(mainJSFile)] = [];
    }

    if (!depsCSS[path.resolve(mainCSSFile)]) {
        depsCSS[path.resolve(mainCSSFile)] = [];
    }

    resolveRequire(mainJSFile, packageFolder);
    resolveCss(mainCSSFile, packageFolder);

    processFolder.pop(packageFolder);
    if (processFolder.length) {
        process.chdir(processFolder[processFolder.length - 1])
    }

}

console.log("depsJS: ", depsJS);
console.log("depsCSS: ", depsCSS);
console.log("depsModules: ", depsModules);
console.log("requireList:", requireList);

function resolveRequire(fileName, mainFolder) {
    var content = fs.readFileSync(fileName, "utf-8");
    var absoluteFileName = path.resolve(fileName);

    if (!depsJS[absoluteFileName]) {
        depsJS[absoluteFileName] = [];
    }

    var temptContent = content;
    content.replace(SLASH_RE, '').replace(REQUIRE_RE, function (m, m1, m2) {
        if (m2) {
            var moduleId;
            if (m2.indexOf(".") >= 0) {
                var absolutePath = path.join(mainFolder, m2);
                var extName = path.extname(absolutePath);

                //避免循环依赖，需要判断是否已经打包
                if (requireList.indexOf(absolutePath) < 0 && (extName === ".js" || extName === ".html")) {
                    moduleId = absolutePath.replace(mainEntry + "/", '');

                    //替换require中的ID
                    var temptArray;
                    temptArray = temptContent.split(m2);
                    temptContent = temptArray.join(moduleId);

                    depsJS[path.resolve(fileName)].push(absolutePath);
                    resolveRequire(absolutePath, mainFolder);
                }

            } else {
                var moduleFolder = path.join(mainEntry, "node_modules", m2);
                var packageFile = path.join(moduleFolder, "package.json");

                if (!depsModules[mainFolder]) {
                    depsModules[mainFolder] = [];
                }

                if (fs.existsSync(packageFile)) {
                    var mainJSFile = packageFile.main || path.join(moduleFolder, "index.js");
                    depsModules[mainFolder].push(moduleFolder);
                    moduleId = mainJSFile.replace(mainEntry + '/', '');

                    //替换require中的ID
                    var temptArray;
                    temptArray = temptContent.split(m2);
                    temptContent = temptArray.join(moduleId);

                    resolveModules(packageFile);
                }
            }

        }

        //将内容写回文件
        fs.writeFileSync(fileName + ".tempt", temptContent);

        return temptContent;
    });

    //得到所有的文件依赖
    if (requireList.indexOf(absoluteFileName) < 0) {
        requireList.push(absoluteFileName);
    }

}

function resolveCss(fileName, mainFolder) {
    var absoluteFileName = path.resolve(fileName);

    if (!fs.existsSync(absoluteFileName)) {
        return;
    }

    var content = fs.readFileSync(fileName, "utf-8");

    if (!depsCSS[absoluteFileName]) {
        depsCSS[absoluteFileName] = [];
    }

    content.replace(SLASH_RE, '').replace(IMPORT_RE, function (m, m1, m2) {
        if (m2) {
            var cssFileNames = m2.replace(/\'|\"/g, "");
            var subFileList = cssFileNames.split(",");

            subFileList.forEach(function (fileItem) {
                var currentFileName = path.resolve(mainFolder, fileItem.trim() + ".scss");
                depsCSS[path.resolve(fileName)].push(currentFileName);
            });
        }
    });
}

/*
 *npm.load(null, function (err) {
 *    npm.commands.ls([], function (err, data, a, b) {
 *        console.log(typeof data);
 *        var item;
 *        for (item in data) {
 *            console.log(item);
 *        }
 *    });
 *});
 */
