// 引入Lodash库，它提供了很多实用的工具函数，用于处理数据、对象、数组等操作，虽然此处未明确体现具体使用的功能，但后续可能会借助它进行一些便捷的数据处理
var _ = require('lodash');
// 引入Node.js的path模块，用于处理文件路径相关的操作，比如拼接、解析路径等
var path = require("path");
// 引入Busboy模块，它常用于处理文件上传的中间件，能够方便地解析包含文件的HTTP请求中的文件数据
var Busboy = require('busboy');
// 引入Node.js的文件系统模块fs，用于对文件进行读写、查询目录等操作
var fs = require("fs");
// 引入uniqid模块，用于生成唯一的标识符，在这里可能用于为上传的文件生成唯一的文件名
var uniqid = require('uniqid');
// 引入UEditor的配置文件，通过拼接当前工作目录和配置文件的相对路径来获取其准确路径，该配置文件可能包含了UEditor相关的各种配置参数，如上传路径、允许的文件类型等
var ueditor_config = require(path.join(process.cwd(), "/config/ueditor.config.js"));
// 引入项目的上传配置信息，通过配置模块（config）获取名为"upload_config"的配置项，里面应该包含了如上传目录、基础URL等与上传相关的配置内容
var upload_config = require('config').get("upload_config");

// 定义允许上传的文件类型列表，以逗号分隔的字符串形式表示，目前包含了常见的图片文件类型以及ico、bmp文件类型
var filetype = 'jpg,png,gif,ico,bmp';

// 将一个函数作为模块的导出内容，这个函数很可能作为中间件在Express等Node.js的Web框架中使用，用于处理不同UEditor相关的请求操作，比如获取配置、上传文件、获取文件列表等
module.exports = function (req, res, next) {
    // 判断请求中的查询参数action的值是否为"config"，如果是，则表示客户端请求获取UEditor的配置信息
    if (req.query.action == "config") {
        // 使用res.jsonp方法将UEditor的配置信息（ueditor_config）返回给客户端，jsonp是一种跨域数据传输的方式，常用于解决浏览器的同源策略限制问题，使得客户端能够获取到配置数据
        res.jsonp(ueditor_config);
    } else if (req.query.action === 'uploadimage' || req.query.action === 'uploadfile' || req.query.action === 'uploadvideo') {
        // 创建一个Busboy实例，用于解析包含文件上传的请求，传入请求头（headers）信息，使得Busboy能够根据请求头中的相关信息（如Content-Type等）来正确解析文件数据
        var busboy = new Busboy({ headers: req.headers });

        // 监听Busboy实例的'file'事件，当解析到文件数据时，该事件会被触发，事件回调函数接收多个参数，用于获取文件相关的各种信息
        busboy.on('file', function (fieldname, file, filename, encoding, mimetype) {
            // 将文件名（filename）按"."进行分割，得到一个包含文件名各部分的数组，用于提取文件的扩展名
            var fileExtArray = filename.split(".");
            // 获取文件扩展名，即分割后的数组中的最后一个元素
            var ext = fileExtArray[fileExtArray.length - 1];
            // 使用uniqid模块生成一个唯一的标识符，并与文件扩展名拼接起来，作为保存文件时使用的文件名，这样可以确保文件名的唯一性，避免文件覆盖等问题
            var save_filename = uniqid() + "." + ext;
            // 拼接文件保存的完整路径，通过结合当前工作目录、配置中的上传目录（upload_config.get("upload_ueditor")）以及生成的文件名（save_filename）来确定最终保存位置
            var savePath = path.join(process.cwd(), upload_config.get("upload_ueditor"), save_filename);

            // 监听文件流（file）的'end'事件，当文件数据全部读取完毕后，该事件会被触发，在这里可以进行一些后续操作，比如组装返回给客户端的文件上传结果信息
            file.on('end', function () {
                // 组装文件上传成功后的结果对象，包含文件的访问URL、标题（可根据请求体中的pictitle字段获取，如果不存在则使用原始文件名）、原始文件名以及表示上传状态为成功的标志
                var result = {
                    'url': upload_config.get("baseURL") + "/" + upload_config.get("upload_ueditor") + "/" + save_filename,
                    'title': req.body && req.body.pictitle || filename,
                    'original': filename,
                    'state': 'SUCCESS'
                };
                // 判断请求中是否包含encode参数，如果有，则使用res.jsonp方法将结果对象以JSONP的形式返回给客户端，同样是考虑到跨域等情况的一种数据返回方式
                if (req.query.encode) {
                    res.jsonp(result);
                } else {
                    // 如果没有encode参数，使用res.redirect方法进行重定向，重定向的URL由配置中的简单上传重定向地址（upload_config.get("simple_upload_redirect")）和文件上传结果信息（经过JSON.stringify转换为字符串形式）拼接而成，这样客户端可以根据重定向后的地址获取到上传结果信息
                    // 另一个被注释掉的res.redirect(result.url)，原本可能是直接重定向到文件的访问URL，但这里采用了传递结果信息的重定向方式
                    res.redirect(upload_config.get("simple_upload_redirect") + "?result=" + JSON.stringify(result));
                }
            });

            // 将文件流（file）通过管道（pipe）写入到创建的可写文件流（fs.createWriteStream(savePath)）中，实现将上传的文件保存到指定的文件路径下
            file.pipe(fs.createWriteStream(savePath));
        });

        // 将请求对象（req）通过管道（pipe）传入到Busboy实例中，触发Busboy开始解析请求中的文件数据，从而进入上述的文件上传处理流程
        req.pipe(busboy);
    } else if (req.query.action === 'listimage') {
        // 使用文件系统模块（fs）的readdir方法读取指定目录下的所有文件，目录路径通过结合当前工作目录和配置中的上传目录（upload_config.get("upload_ueditor")）来确定，读取完成后会调用回调函数处理结果（err表示读取过程中是否出现错误，files表示读取到的文件列表）
        fs.readdir(path.join(process.cwd(), upload_config.get("upload_ueditor")), function (err, files) {
            // 如果读取过程中出现错误，直接结束响应，不返回任何数据给客户端（这里可以考虑返回更合适的错误信息给客户端）
            if (err) return res.end();
            // 初始化一个变量用于统计符合条件的文件总数，初始值为0
            var total = 0;
            // 创建一个空数组，用于存放符合条件的文件信息，后续会将满足文件类型要求的文件相关信息添加到这个数组中
            var filelist = [];

            // 使用Lodash的forEach方法遍历读取到的所有文件，对每个文件进行相关处理
            _(files).forEach(function (file) {
                // 将文件名按"."进行分割，获取文件扩展名，用于后续判断文件类型是否符合要求
                var fileExtArray = file.split(".");
                var ext = fileExtArray[fileExtArray.length - 1];
                // 判断文件扩展名是否在允许的文件类型列表（filetype）中（将扩展名转换为小写后进行判断），如果是，则表示该文件符合要求，进行相应的信息组装和添加到文件列表操作
                if (filetype.indexOf(ext.toLowerCase()) >= 0) {
                    var result_file = {};
                    // 组装文件的访问URL，格式与前面文件上传成功后的URL格式类似，通过配置中的基础URL、上传目录以及文件名来确定
                    result_file.url = upload_config.get("baseURL") + "/" + upload_config.get("upload_ueditor") + "/" + file;
                    // 将组装好的文件信息对象添加到文件列表数组中
                    filelist.push(result_file);
                    // 符合条件的文件总数加1
                    total++;
                }
            });

            // 使用res.jsonp方法将包含文件列表信息、状态（SUCCESS表示成功获取列表）、起始索引（这里固定为1）以及文件总数的结果对象返回给客户端，同样采用JSONP的方式考虑跨域等情况进行数据传输
            res.jsonp({
                "state": "SUCCESS",
                "list": filelist,
                "start": 1,
                "total": total
            });
        })
    }
}