/**
 * ajaxfileupload.js
 * 基于 XMLHttpRequest 实现，完全兼容原有 API，支持进度监控
 * 
 * ==================== 使用方法 ====================
 * 
 * 1. 基础上传
 *    $.ajaxFileUpload({
 *        url: '/upload',
 *        fileElementId: 'fileInput',  // input[type="file"] 的 ID
 *        dataType: 'json',
 *        success: function(data, status) {
 *            console.log('上传成功:', data);
 *        },
 *        error: function(xhr, status, error) {
 *            console.error('上传失败:', error);
 *        },
 *        complete: function(xhr, status) {
 *            console.log('上传完成:', status);
 *        }
 *    });
 * 
 * 2. 带进度监控的上传
 *    $.ajaxFileUpload({
 *        url: '/upload',
 *        fileElementId: 'fileInput',
 *        dataType: 'json',
 *        progress: function(percent, loaded, total) {
 *            // percent: 上传百分比 (0-100)
 *            // loaded: 已上传字节数
 *            // total: 总字节数
 *            console.log('上传进度: ' + percent + '%');
 *            $('#progressBar').css('width', percent + '%');
 *            $('#progressText').text(percent + '%');
 *        },
 *        success: function(data, status) {
 *            console.log('上传成功:', data);
 *        },
 *        error: function(xhr, status, error) {
 *            console.error('上传失败:', error);
 *        }
 *    });
 * 
 * 3. 带附加数据的上传
 *    $.ajaxFileUpload({
 *        url: '/upload',
 *        fileElementId: 'fileInput',
 *        dataType: 'json',
 *        data: {
 *            userId: 123,
 *            type: 'avatar'
 *        },
 *        success: function(data, status) {
 *            console.log('上传成功:', data);
 *        }
 *    });
 * 
 * 4. 取消上传
 *    var upload = $.ajaxFileUpload({
 *        url: '/upload',
 *        fileElementId: 'fileInput',
 *        dataType: 'json',
 *        success: function(data, status) {
 *            console.log('上传成功:', data);
 *        }
 *    });
 *    
 *    // 取消上传
 *    upload.abort();
 * 
 * ==================== 配置参数 ====================
 * 
 * @param {string} url              - 上传地址 (必填)
 * @param {string} fileElementId    - 文件输入框的 ID (必填)
 * @param {string} dataType         - 返回数据类型: 'json', 'xml', 'html', 'script', 'text' (默认: 自动检测)
 * @param {object} data             - 附加的表单数据 (可选)
 * @param {number} timeout          - 超时时间，单位毫秒 (可选)
 * @param {object} headers          - 自定义请求头 (可选)
 * @param {boolean} global          - 是否触发全局 AJAX 事件 (默认: true)
 * @param {function} progress       - 进度回调函数: function(percent, loaded, total) (可选)
 * @param {function} success        - 成功回调函数: function(data, status) (可选)
 * @param {function} error          - 错误回调函数: function(xhr, status, error) (可选)
 * @param {function} complete       - 完成回调函数: function(xhr, status) (可选)
 * 
 * ==================== 浏览器兼容性 ====================
 * 
 * - Chrome 所有版本
 * - Firefox 所有版本
 * - Safari 所有版本
 * - Edge 所有版本
 * 
 */
(function($) {
    'use strict';

    $.extend({
        handleError: function (s, xhr, status, e) {
            if (s.error) {
                s.error.call(s.context || s, xhr, status, e);
            }
            if (s.global) {
                $(document).trigger("ajaxError", [xhr, s, e]);
            }
        },

        createUploadIframe: function (id, uri) {
            return null;
        },

        createUploadForm: function (id, fileElementId, data) {
            return null;
        },

        ajaxFileUpload: function (s) {
            s = $.extend({}, $.ajaxSettings, s);
            var id = new Date().getTime();
            var requestDone = false;

            var fileElement = typeof s.fileElementId === 'string'
                ? document.getElementById(s.fileElementId)
                : s.fileElementId;

            if (s.global && !$.active++) {
                $(document).trigger("ajaxStart");
            }

            var xml = {
                responseText: null,
                responseXML: null,
                status: 0,
                statusText: ''
            };

            if (s.global) {
                $(document).trigger("ajaxSend", [xml, s]);
            }

            var xhr = new XMLHttpRequest();
            var formData = new FormData();
            var fileInput = $(fileElement)[0];

            if (fileInput && fileInput.files && fileInput.files[0]) {
                formData.append(fileInput.name || 'file', fileInput.files[0]);
            }

            if (s.data) {
                for (var key in s.data) {
                    if (s.data.hasOwnProperty(key)) {
                        formData.append(key, s.data[key]);
                    }
                }
            }

            // 进度监控支持
            if (s.progress) {
                xhr.upload.addEventListener('progress', function(e) {
                    if (e.lengthComputable) {
                        var percent = Math.round((e.loaded / e.total) * 100);
                        s.progress(percent, e.loaded, e.total);
                    }
                });
            }

            xhr.addEventListener('load', function() {
                requestDone = true;
                xml.status = xhr.status;
                xml.statusText = xhr.statusText;
                xml.responseText = xhr.response;

                var status = xhr.status >= 200 && xhr.status < 300 ? 'success' : 'error';

                if (status === 'success') {
                    var data = xhr.response;

                    if (s.dataType === 'json') {
                        try {
                            data = JSON.parse(data);
                        } catch (e) {
                            $.handleError(s, xml, 'parseerror', e);
                            if (s.complete) s.complete(xml, 'error');
                            if (s.global) {
                                $(document).trigger("ajaxComplete", [xml, s]);
                                if (!--$.active) {
                                    $(document).trigger("ajaxStop");
                                }
                            }
                            return;
                        }
                    }

                    if (s.success) {
                        s.success(data, status);
                    }

                    if (s.global) {
                        $(document).trigger("ajaxSuccess", [xml, s]);
                        $(document).trigger("ajaxComplete", [xml, s]);
                    }
                } else {
                    $.handleError(s, xml, status);
                    if (s.global) {
                        $(document).trigger("ajaxComplete", [xml, s]);
                    }
                }

                if (s.global && !--$.active) {
                    $(document).trigger("ajaxStop");
                }

                if (s.complete) {
                    s.complete(xml, status);
                }
            });

            xhr.addEventListener('error', function() {
                requestDone = true;
                $.handleError(s, xml, 'error', new Error('Network Error'));
                if (s.global) {
                    $(document).trigger("ajaxComplete", [xml, s]);
                    if (!--$.active) {
                        $(document).trigger("ajaxStop");
                    }
                }
                if (s.complete) s.complete(xml, 'error');
            });

            xhr.addEventListener('abort', function() {
                requestDone = true;
                $.handleError(s, xml, 'abort', new Error('Request Aborted'));
                if (s.global) {
                    $(document).trigger("ajaxComplete", [xml, s]);
                    if (!--$.active) {
                        $(document).trigger("ajaxStop");
                    }
                }
                if (s.complete) s.complete(xml, 'abort');
            });

            xhr.open('POST', s.url);
            
            // 添加 AJAX 请求头，让服务器识别为 AJAX 请求
            xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');

            if (s.timeout > 0) {
                xhr.timeout = s.timeout;
                xhr.addEventListener('timeout', function() {
                    requestDone = true;
                    $.handleError(s, xml, 'timeout', new Error('Request Timeout'));
                    if (s.global) {
                        $(document).trigger("ajaxComplete", [xml, s]);
                        if (!--$.active) {
                            $(document).trigger("ajaxStop");
                        }
                    }
                    if (s.complete) s.complete(xml, 'timeout');
                });
            }

            if (s.headers) {
                for (var header in s.headers) {
                    if (s.headers.hasOwnProperty(header)) {
                        xhr.setRequestHeader(header, s.headers[header]);
                    }
                }
            }

            xhr.send(formData);

            return {
                abort: function () {
                    xhr.abort();
                }
            };
        },

        uploadHttpData: function (r, type) {
            var data = !type;
            data = type === "xml" || data ? r.responseXML : r.responseText;

            if (type === "script") {
                var script = document.createElement('script');
                script.text = data;
                document.head.appendChild(script).parentNode.removeChild(script);
            }

            if (type === "json") {
                try {
                    data = JSON.parse(data);
                } catch (e) {
                    data = null;
                }
            }

            if (type === "html") {
                var $div = $("<div>").html(data);
                $div.find("script").each(function() {
                    var script = document.createElement('script');
                    script.text = $(this).html();
                    document.head.appendChild(script).parentNode.removeChild(script);
                });
                data = $div.html();
            }

            return data;
        }
    });

})(jQuery);
