var Component = Component || {GUID:1};
(function (comp) {
    /**
     * 文件加载状态
     * @type {Object}
     */
    var REQ_STATUS = {'WAITING':0, "DOING":1, 'SUCCESS':2, 'FAILURE':3};

    /**
     * 资源管理器
     */
    var ResourceManager = comp.ResourceManager = function (opt) {
        this.callback = [];
        this.countLoaded = 0;
        this.queen = [];
        this.bandWidth = opt.bandWidth || 3;
    };

    /**
     * 获得队列中的正在执行的数目
     * @param jRes
     * @private
     */
    ResourceManager.prototype._getWorkingCount = function () {
        return this.queen.filter(
            function (val) {
                return val.status == REQ_STATUS.DOING;
            }).length;
    };
    /**
     * 获得队列中的已执行的数目
     * @param jRes
     * @private
     */
    ResourceManager.prototype._getDoneCount = function () {
        return this.queen.filter(
            function (val) {
                return (val.status == REQ_STATUS.FAILURE) || (val.status == REQ_STATUS.SUCCESS);
            }).length;
    };
    /**
     * 获得队列中的等待执行的数目
     * @param jRes
     * @private
     */
    ResourceManager.prototype._getWaitingCount = function () {
        return this.queen.filter(
            function (val) {
                return val.status === REQ_STATUS.WAITING;
            }).length;
    };
    /**
     * 获得队列中的下一个待执行请求
     * @param jRes
     * @private
     */
    ResourceManager.prototype._getNext = function () {
        for (var i = 0, l = this.queen.length; i < l; i++) {
            if (this.queen[i].status === REQ_STATUS.WAITING) {
                return this.queen[i];
                break;
            }
        }
        return null;
    };
    /**
     * 出入队列方法
     * @param res 如果res为false，则为出队操作
     */
    ResourceManager.prototype._next = function (bandCount) {
        //如果队列不为空，且执行中的文件小于带宽
        if (this.queen.length > 0 && this._getWorkingCount() < this.bandWidth) {
            //如果有需要出队的文件
            if (this._getWaitingCount() > 0) {
                if(typeof(bandCount)=='undefined'){bandCount=1;}
                    for(var i=0;i<bandCount;i++){
                        this._loadByOne(this._getNext());
                    }
            }
        }
    }

    /**
     * 停止加载,取消加载
     */
    ResourceManager.prototype.stop = function () {
        this.resObj && (this.resObj.resArray = []);
    };

    /**
     * 恢复加载
     */
    ResourceManager.prototype.resume = function (n) {
        this.bandWidth = n || 3;
    };

    /**
     * 暂停加载
     */
    ResourceManager.prototype.pause = function () {
        this.bandWidth = 0;
    };

    /**
     * 用XMLHttpRequest请求文件
     * @param one
     * @private
     */
    ResourceManager.prototype._loadXHR = function (one) {
        var that = this;
        var _xmlhttp = new XMLHttpRequest();
        _xmlhttp.open((one.data ? "POST" : "GET"), one.src, true);
        _xmlhttp.addEventListener("progress", function (evt) {
            console.log("progress file:" + evt.lengthComputable);
            if (evt.lengthComputable) {
                var percentComplete = Math.round(event.loaded * 100 / event.total);
                that.fire({
                    type:'progress',
                    args:[that.countLoaded, that.queen.length, percentComplete, one]
                });
            }
        }, false);
        _xmlhttp.onreadystatechange = function () {
            if (this.readyState == 4) {
                if (this.status == 200) {
                    that._done(one, true, _xmlhttp.responseText);
                } else {
                    that._done(one, false, false);
                }
            }
        };
        if (one.data) {
            _xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            _xmlhttp.send(one.data);
        } else {
            _xmlhttp.send();
        }
    }

    ResourceManager.prototype.reset=function(){
        //this.callback=[];
        this.countLoaded = 0;
    }
    /**
     * 用Dom节点的方式加载文件
     * @param one
     * @private
     */
    ResourceManager.prototype._loadDom = function (one) {
        var that = this;
        var e = document.createElement(one.type);
        e.id = 'e_' + comp.GUID++;
        var _src = (typeof one == 'object') ? one.src : one;
        switch (one.type) {
            case 'script':
                e.type = "text/javascript";
                document.head.appendChild(e);
                e.src = one.path + _src;
                break;
            case 'link':
                e.type = "text/css";
                e.rel = "stylesheet";
                e.href = one.path + _src;
                document.head.appendChild(e);
                break
            default:
                e.src = one.path + _src;
                break;
        }

        e.onload = function (evt) {
            that._done(one, true, true);
        };
        e.onerror = function (evt) {
            that._done(one, false, false);
        };
    }

    ResourceManager.prototype._done = function (res, result, data) {
        res.status = result ? REQ_STATUS.SUCCESS : REQ_STATUS.FAILURE;
        //console.log("loaded file:" + res.src);
        //如果列表中，还有未完成的相同文件，则不增加已加载数，此处有bug,如果同一条列表中有两个相同的文件，则始终不会current==total
        //if(this.queen.filter(function (val) {return val.src === res.src&&val.status==REQ_STATUS.WAITING;}).length <1){
            this.countLoaded++;
        //}
        //console.log("loaded file:" + this.countLoaded);
        //console.log("res.parent.resArray.length"+res.parent.resArray.length);
        this.fire({
            type:'loading',
            args:[this.countLoaded, this.queen.length, data, res]
        });
        this._next();
    }

    /**
     * 逐个加载
     * @param res
     * @return {Boolean}
     * @private
     */
    ResourceManager.prototype._loadByOne = function (res) {
        if (!res)return false;
        var that = this, one = res;
        //如果在队列中正在下载，则等待该文件下载完成再继续
        /*
        if (this.queen.filter(function (val) {return val.src === res.src&&val.status==REQ_STATUS.DOING;}).length >= 1) {
            console.log('res'+res);
            setTimeout(function(){that._loadByOne(res)},1000);
            return false;
        }
        */
        //如果已缓存过该文件
        if (this.queen.filter(function (val) {return val.src === res.src&&val.status==REQ_STATUS.SUCCESS;}).length > 0) {
            this._done(one, true, true);
            return false;
        }

        //下载中
        one.status = REQ_STATUS.DOING;
        switch (one.type) {
            case 'ajax':
            //case 'link':
                that._loadXHR(one);
                break;
            default:
                that._loadDom(one);
                break;
        }
    }

    /**
     * 开始加载资源
     * @param jRes
     */
    ResourceManager.prototype.start = function (jRes,recursion) {
        //如果传入的是数组
        if (jRes instanceof Array) {
            for (var i = 0, l = jRes.length; i < l; i++) {
                arguments.callee.call(this, jRes[i],true);
            }
            this._next(this.bandWidth);
        } else {
            var resArray = jRes.resArray;

            for (var i = 0, l = resArray.length; i < l; i++) {
                var _res;
                if(typeof resArray[i] =='object'){
                    _res = resArray[i];
                }else{
                    _res = {src:resArray[i]};
                    _res.type = jRes.type || 'image';
                }
                _res.path = jRes.path || '';
                _res.parent=jRes;
                _res.status = 0;
                this.queen.push(_res);
            }
            //如果是单数组加载任务请求，那么直接开始下载，如果是在递归里，就在最上层请求
            if(!recursion){
                this._next(this.bandWidth);
            }
        }
    };

    /**
     * 注册事件监听行为
     * @param startcb
     * @param updatecb
     * @param finishcb
     */
    ResourceManager.prototype.bind = function (callback) {
        if (callback) {
            this.callback.push(callback);
        }
    }

    /**
     * 触发加载行为的回调
     * @param jData
     */
    ResourceManager.prototype.fire = function (jData) {
        for (var i = 0; i < this.callback.length; i++) {
            this.callback[i].call(this, jData);
        }
    }
})(Component);
