;
(function () {
    const event = require('myevents'),
        DownFile = require('downfile'),
        taskStatus = require('taskstatus'),
        appCache = require('app-cache'),
        path = require('path'),
        downTaskList = require('downtask'),
        transfer = require('transfer'),
        dbServer = require('db-server'),
        apiService = require('app-service'),
        mkpath = require('mkpath'),
        md5 = require('md5');

    let cacheConfig = appCache.local_config();
    let folderTask = {};
    var task = {
        parallelDownloadNum: cacheConfig.task.down_num,
        addTask: function (upload) {

            let downfile = new DownFile(upload),
                down_options = downfile.options;

            if (!downTaskList.add(down_options))
                return task.startNext(); //如果已经存在了，进行下一波的下载

            return wfsGateway(down_options).then(host => {
                if (host) {
                    down_options.url = host;
                    down_options.status = taskStatus.doing;
                } else {
                    down_options.status = taskStatus.netError;
                }
                return dbServer.down.status(down_options._id, down_options.status);
            }).then(e => {
                if (down_options.status === taskStatus.doing)
                    downfile.start();
                else {
                    downTaskList.remove(downfile._id);
                }
                event.emit('down_change_ctr', down_options);
            });
        },
        pause: function (id) {
            var downfile = downTaskList.find(id);
            if (downfile) {
                downfile.status = taskStatus.pause;
                downTaskList.remove(id);
            };
            dbServer.down.status(id, taskStatus.pause).then(e => {
                task.startNext();
            });
        },
        startNext: function (id) {
            if (downTaskList.taskNum >= task.parallelDownloadNum) {
                id && dbServer.down.status(id, taskStatus.wait);
                return false;
            };
            return nextTask(id).then(doc => {
                if (!doc) {
                    return id && event.emit('down_complete_ctr', { _id: id });
                }
                if (downTaskList.taskNum >= task.parallelDownloadNum)
                    return dbServer.down.status(id, taskStatus.wait);
                return task.addTask(doc);
            });
        },
        remove: function (id) {
            var options = downTaskList.find(id);
            if (options) options.status = taskStatus.stop;
            return dbServer.down.remove(id).then(e => {
                downTaskList.remove(id);
                task.startNext();
            });
        },
        stop: function (id) {
            let options = downTaskList.find(id);
            if (options) options.status = taskStatus.stop;
            dbServer.down.status(id, taskStatus.stop).then(e => {
                downTaskList.remove(id);
                task.startNext();
            });
        },
        clearQueue: function () {
            return dbServer.down.clear().then(e => {
                let list = downTaskList.list();
                for (let e in list) {
                    list[e].status = taskStatus.stop;
                };
                downTaskList.clear();
            });
        },
        stopQueue: function () {
            return dbServer.down.status({}, taskStatus.pause).then(e => {
                let list = downTaskList.list();
                downTaskList.stopAll();
                for (let e in list) {
                    list[e].status = taskStatus.pause;
                };
                downTaskList.clear();
            });
        },
        startQueue: function () {
            return dbServer.down.status({}, taskStatus.wait).then(e => {
                let num = cacheConfig.task.upload_num;
                downTaskList.startAll();
                do {
                    num = num - 1;
                    task.startNext();
                } while (num)
            });
        },
        _onDownComplete: function (file) {
            return task.remove(file._id).then(() => {
                let num = cacheConfig.task.upload_num;
                do {
                    num = num - 1;
                    task.startNext();
                } while (num)
                event.emit('down_complete_ctr', file);
                event.emit('down_notice', file);
                event.emit('task_num_change');
            });
        },
        _onRangeFinish: function (file) {
            event.emit('down_change_ctr', file);
            dbServer.down.downRange(file._id, file.end_len);
        },
        _onPause: function (file) {
            task.startNext();
            event.emit('down_change_ctr', file);
        },
        _onError: function (file) {
            task.startNext();
            event.emit('down_change_ctr', file);
        },
        _onOvertime: function (file) {

        }
    };

    event.on('down_complete', task._onDownComplete);

    event.on('range_finish', task._onRangeFinish);

    event.on('down_pause', task._onPause);

    event.on('down_error', task._onError);
    event.on('down_overtime', task._onOvertime);

    function wfsGateway(down) {
        return transfer.wfsGateway.download(down.md5).then(e => {
            if (e && e.ret !== 0) {
                return e.url;
            }
            return false;
        });
    }

    function nextTask(id) {
        if (id)
            return dbServer.down.findOne({ '_id': id }).then(addTask);

        return dbServer.down.nextTask().then(addTask);

        function addTask(doc) {

            if (!doc) {
                return false;
            }

            if (doc.isdir == 1) {
                if (folderTask[doc.fileid]) {
                    task.startNext();
                    return false;
                }
                folderTask[doc.fileid] = true;

                return task._onDownComplete(doc).then(() => {
                    mkpath.sync(doc.path);
                    // event.emit('down_complete_ctr', { _id: doc._id });
                    return apiService.item_list(doc.fileid)

                }).then(function (d) {
                    let new_tasks = d.data.map((v,index) => ({
                        'fileid': v._id,
                        'isdir': v.isdir,
                        "md5": v.md5,
                        "name": v.name,
                        "size": v.size,
                        "path": path.join(doc.path, v.name),
                        "status": 0,
                        "url": '',
                        'start_len': 0,
                        'sort':index
                    }));

                    if (new_tasks.length)
                        return dbServer.down.add(new_tasks);
                    return false;
                }).then((newDocs) => {

                    if (newDocs && newDocs.length) {
                        event.emit('updataDownTaskNum', newDocs.length);
                        event.emit('down_taskList', newDocs);
                        event.emit('task_num_change');
                    }

                    delete folderTask[doc.fileid];
                    task.startNext();
                    return false
                });
            }
            return doc;
        }

    }
    module.exports = task;

}());