"use strict";
/**
    面向切面编程的辅助模块
    
    Feartures : 
        1. promiseEvent :基于promise和event机制的回调管理
        2. trigger :对象触发器
        3. flowController :流程/生命周期控制器

    Update Note:
        + 2014.8.06 :将priorityList应用到promiseEvent中
        + 2014.6.13 :trigger添加属性变化监听支持
        + 2014.6.11 :promiseEvent添加非阻塞模式
        + 2014.5 :Created

    @module AOP
*/
_stDefine('aop', function(st) {
    var sliceArgs = st.sliceArgs;

    //设置默认权重
    st.conf("aop-Priority", 0);

    function isDefined(data) {
        return data !== undefined;
    }

    function PromiseSign(mode) {
        this.mode = mode;
    }

    //promise参数对象
    function PromiseArg(prop) {
        st.mergeObj(this, prop);
        this.promise = function(mode) {
            return new PromiseSign(mode);
        }
    }

    function buildPromiseArg(prop) {
        return new PromiseArg(prop);
    }

    //判断是否promise
    function isPromise(result) {
        return result ? result instanceof PromiseSign : false;
    }


    //判断是否promise参数
    function isPromiseArg(d) {
        if (d && typeof d === 'object') {
            return d instanceof PromiseArg;
        }
        return false;
    }

    function openPromise(defer, _err) {
        if (_err) {
            setTimeout(function() {
                defer.reject(_err);
            }, 0);
        }
        return defer.promise();
    }

    /**
        基于事件和promise的回调管理,类似于jquery的callbacks,但具有结果传递,优先级,事件参数,promise控制等功能;
        默认注册的事件都是按照优先级,依次执行,无论同步还是异步;但在非阻塞模式下,则事件不会等待上一个执行完毕(异步),
        直接回依次执行,只是在最后的结果中会等待所有的事件执行完毕之后才返回
        @class promiseEvent
        @constructor
        @param [mode] {string} promiseEvent的模式,可以混用;
            1. 默认;event模式,所有的注册的事件,执行时,第一个事件参数为e(详细说明见promiseEvent-EventArg)
            2. 'callback' : 回调模式; 与event模式对立,执行时不会添加事件参数e
            2. 'once' : 全部事件执行一次,即有执行动作就销毁
            3. 'noBlock' : 非阻塞模式;
        @demo test/base/aop.js [add] {基础}
        @demo test/base/aop.js [Once Mode] {once模式}
        @demo test/base/aop.js [callback mode] {callback模式}
        @demo test/base/aop.js [promise - result] {promise示例}
        @demo test/base/aop.js [noBlock mode] {非阻塞模式}
        @demo test/base/aop.js [Transfer Result] {结果传递}
    */
    function promiseEvent(mode) {
        var _mode, _callbackMode, _noBlock,
            _onceMode,
            _list = st.priorityList("self", st.conf("aop-Priority"));

        if (mode) {
            _mode = mode.split(' ');
            _onceMode = checkMode('once');
            _callbackMode = checkMode('callback');
            //非阻塞模式
            _noBlock = checkMode('noBlock');
            _mode = null;
        }

        function checkMode(m) {
            return _mode.indexOf(m) > -1;
        }

        /**
            清空所有事件回调
            @method clear 
            @chainable
            @demo test/base/aop.js [clear]
        */
        function clear() {
            _list.clear();
            return this;
        }

        /**
            添加事件回调方法
            @method add 
            @param name {string} 事件回调名
            @param fn {string} 事件回调方法
            @param [priority=0] {number} 权重;预设为0,可以通过配置调整
            @param [mode] {string} 回调模式:"once":执行一次
            @chainable
            @demo test/base/aop.js [add]
        */
        function add(name, fn, priority, mode) {
            if (!name && typeof name !== 'string' && !fn)
                return;

            if(typeof (priority) === 'string') {
                mode = priority;
                priority = null;
            }

            _list.add({
                name: name,
                fn: fn,
                priority: priority,
                mode: mode
            });
            return this;
        }

        /**
            删除事件回调方法
            @method remove 
            @param name {string} 事件回调名
            @chainable
            @demo test/base/aop.js [remove]
        */
        function remove(name) {
            _list.remove(function(item) {
                return item.name === name;
            })
            return this;
        }

        /**
            根据上下文对象执行回调;fire方法的增强
            @method fireWith 
            @param context {object} 上下文对象
            @param args {array} 执行参数
            @param [argHandle] {function} 参数处理方法,可以对eventarg进行修改;例如:argHandle(e)
            @return {object|promise} 返回执行结果
            @demo test/base/aop.js [fireWith]
        */
        function fireWith(context, args, argHandle) {
            var i = 0,
                fireCount = 0,
                itemNoBlock,
                len = _list.len(),
                item, defer, _result, _err, d, _stop, _done;

            if (!len)
                return;

            if (typeof argHandle !== 'function')
                argHandle = null;

            /**
                promiseEvent中事件回调的EventArg(e)参数对象;通过EventArg可以对事件进行阻止冒泡、promise、事件删除还有结果传递等控制;
                EventArg针对上下文对象(比较trigger和flowController)下,具有的独立的方法;
                @class EventArg
            */
            d = buildPromiseArg({
                /**
                    停止所有后续事件执行
                    @method stopPropagation 
                    @chainable
                    @demo test/base/aop.js [StopPropagation]
                */
                stopPropagation: function() {
                    _stop = true;
                    return this;
                },
                /**
                    完成契约
                    @method resolve 
                    @param [result] {object} 返回结果
                    @demo test/base/aop.js [promise - resolve]
                    @demo test/base/aop.js [promise - multi]
                    @demo test/base/aop.js [promise - noBlock]
                */
                resolve: function(result) {
                    fireCount++;
                    isDefined(result) && (_result = result);
                    _stop ? done() : fireItem();
                },
                /**
                    拒绝契约,在任何一个事件中reject都会停止所有后续promiseEvent的执行
                    @method reject 
                    @param err {object} 拒绝参数
                    @demo test/base/aop.js [promise - reject]
                */
                reject: function(err) {
                    fail(err);
                },
                /**
                    删除当前事件;与promiseEvent.add的'once'模式,不同在于可以手动进行控制
                    @method remove 
                    @chainable
                    @demo test/base/aop.js [promise - remove]
                */
                remove: function() {
                    _list.remove(--i);
                    len--;
                    return this;
                }
            });

            //callback模式下不用添加事件参数
            if (!_callbackMode) {
                args = args ? [d].concat(args) : [d];
                argHandle && argHandle(d);
            }

            function done() {
                _onceMode && clear();
                _done = true;
                defer && defer.resolve(_result);
            }

            function fail(err) {
                _err = err
                defer && defer.reject(err);
            }

            function fireItem(noblock) {
                var result;

                isDefined(_result) && (d.result = _result);

                if (i < len) {
                    if (item = _list.at(i++)) {

                        item.mode === 'once' && d.remove();

                        result = item.fn.apply(context, args);

                        if (isPromise(result)) {
                            if (_noBlock)
                                fireItem();
                            //单项noBlock模式
                            else if (result.mode === "noBlock") {
                                itemNoBlock = true;
                                fireItem();
                            }
                        } else
                            d.resolve(result);
                    }
                } else {
                    //noblock模式下,判断执行数
                    if (!(itemNoBlock || _noBlock) || fireCount === len)
                        done();
                }
            }

            fireItem();

            if (_done) {
                return _result;
            }

            defer = st.Deferred();

            return openPromise(defer, _err);
        }

        /**
            判断是否存在事件回调
            @method has 
            @for promiseEvent
            @param name {string} 事件回调名
            @return {boolean} 是否存在
            @demo test/base/aop.js [has]
        */
        function has(name) {
            var result = false;
            _list.each(function(item) {
                if (item.name === name) {
                    result = true;
                    return false;
                }

            })
            return result;
        }


        return {
            add: add,
            has: has,
            /**
             * 获取注册的事件长度/数
             * @method len
             * @return {number} 注册的事件长度/数
             */
            len : function(){
                return _list.len();
            },
            remove: remove,
            /**
                执行回调
                @method fire 
                @for promiseEvent
                @param args {array} 执行参数
                @param [argHandle] {function} 参数处理方法,可以对eventarg进行修改;例如:argHandle(e)
                @return {object} 返回执行结果
            */
            fire: function() {
                return fireWith(null, sliceArgs(arguments));
            },
            fireWith: fireWith,
            clear: clear
        }
    }

    //trigger的接口设置
    var _interface = {
            onHandler: "onHandler",
            fireHandler: "fireHandler",
            on: "on",
            onBefore: "onBefore",
            onRound: "onRound",
            onError: "onError",
            off: "off",
            offBefore: "offBefore",
            extend: "extend"
        },
        //注入类型
        trTypes = ['before', 'after', 'round', 'error'],
        defineProperty = Object.defineProperty;

    /**
            给对象添加触发器功能,在目标对象上加入触发器功能,目标对象的方法就会具有方法和属性注入功能;所有注入方法使用promiseEvent管理
            目前有四种注入方式: 
            1. before,前置注入,在目标方法执行之前执行;
            2. after,后置执行,在目标方法执行之后执行;
            3. round,环绕,将目标方法包装,自定义控制;
            4. error,错误,捕获reject的事件;
            
            @class attachTrigger
            @constructor
            @param target [object] 目标对象
            @param [mode] [string] 注入前置和后置所采用的promiseEvent的模式,具体见promsieEvent的add
            @param [fnInterface] {object} ;自定义接口方法;在使用attachTrigger方法后,会在target上附加一些控制方法,为了避免重名和控制对外的方法,使用fnInterface来自定义
            @return {trigger} 返回附加上了trigger的对象;
            @demo test/base/aop.js [Bind Test] {基本注册}
            @demo test/base/aop.js [Bind Child] {子对象注册}
            @demo test/base/aop.js [Custom Interface] {自定义接口}
            @demo test/base/aop.js [callback mode] {callback模式}
            @demo test/base/aop.js [all promise] {promise}
            @demo test/base/aop.js [promise - transfer result] {promise结果传递}
            @demo test/base/aop.js [watch prop change] {属性监听}
    */
    function attachTrigger(target, mode, fnInterface) {
        if (!target && typeof target !== 'object')
            return;

        var _trMap = {},
            _fnMap = {},
            _mode, _eventMode,
            _target = target;


        if (typeof mode === 'object')
            fnInterface = mode;
        else
            _mode = mode;

        function getMap(name, create) {
            var map = _trMap[name];
            if (!map && create)
                map = _trMap[name] = {};
            return map;
        }

        function find(name, type, create) {
            var map = getMap(name, create),
                tr;

            if (!type)
                type = "after";

            if (map) {
                tr = map[type];
                if (!tr && create)
                    tr = map[type] = promiseEvent(type === trTypes[3] ? "callback" : _mode);
            }
            return tr;
        }

        function remove(name, type, trName) {
            var tr = find(name, type);
            if (tr) {
                if (trName) {
                    if (st.isArray(trName)) {
                        st.each(trName, function(i, n) {
                            tr.remove(n)
                        })
                    } else
                        tr.remove(trName)
                } else
                    tr.clear();
            }
        }

        function bind(name, trName, fn, type, priority, mode) {
            var args = arguments,
                argsLen = args.length,
                baseFn = _fnMap[name],
                _name = name,
                _fn = fn,
                _type, _priority, _mode,
                roundMode, _targetFn, i = 3,
                arg, argType, bindFn, isProp;

            if (argsLen < i)
                return;

            if (typeof name !== 'string' || typeof trName !== 'string' || typeof fn !== 'function')
                return;

            //判断参数type, priority, mode的重载
            if (argsLen > i) {
                for (; i < argsLen; i++) {
                    arg = args[i];
                    argType = typeof arg;

                    if (argType === 'boolean')
                        _type = arg;
                    if (argType === 'number')
                        _priority = arg;
                    else if (argType === 'string') {
                        if (trTypes.indexOf(arg) > -1)
                            _type = arg;
                        else
                            _mode = arg;
                    }
                }
                roundMode = _type === trTypes[2];
            }

            if (!baseFn) {
                baseFn = _fnMap[_name] = st.getObj(_target, _name);
                if (!baseFn)
                    return;

                //是否为属性绑定
                isProp = typeof baseFn !== 'function';

                if (isProp) {

                    //判断是否roundMode,支持属性定义
                    if (roundMode || !defineProperty)
                        return;

                    baseFn = function(value) {
                        return _fnMap[_name] = value;
                    }
                }

                bindFn = function() {
                    var _result, d, dTrans, _err, _done, defer, callArgs, args = callArgs = sliceArgs(arguments),
                        _stop, _preventDefault, dTransResolve, oldValue,originFn;

                    //属性模式取出原来的值
                    if(isProp){
                        oldValue = _fnMap[_name];
                        originFn =  baseFn;
                    }
                    else {
                        originFn = _fnMap[_name] || baseFn;
                    }

                    function done() {
                        _done = true;
                        //恢复传递的事件resolve方法
                        dTrans && dTransResolve && (dTrans.resolve = dTransResolve);
                        defer && defer.resolve(_result);
                    }

                    function fail(err) {
                        _err = err;
                        defer && defer.reject(err);
                        fire(_name, [err].concat(args), null, trTypes[3])
                    }

                    function setResult(result) {
                        isDefined(result) && (_result = result);
                    }

                    function whenFire(fireResult, success) {
                        st.when(fireResult).then(function(result) {
                            success(result);
                        }, fail);
                    }

                    /**
                        trigger下的事件参数,由EventArg扩展而来
                        @class EventArg(trigger)
                        @extends EventArg
                    */
                    /**
                        阻止默认的方法执行;
                        @method preventDefault
                        @chainable
                        @demo test/base/aop.js [preventDefault]
                        @demo test/base/aop.js [stopPropagation && preventDefault]
                    */
                    function preventDefault() {
                        _preventDefault = true;
                        return this;
                    }

                    /**
                        停止当前方法执行和后置所有事件;在属性监听时,则阻止赋值;
                        @method stop
                        @chainable
                        @demo test/base/aop.js [stop]
                    */
                    function stopFn() {
                        _preventDefault = _stop = true;
                        return this;
                    }

                    //处理传递的时间参数
                    if (args.length && isPromiseArg(args[0])) {
                        dTrans = args[0];
                        dTransResolve = dTrans.resolve;
                        //替换resolve方法
                        dTrans.resolve = function(result) {
                            dTrans.resolve = dTransResolve;
                            dTransResolve = null;

                            setResult(result);
                            fireAfter();
                        }
                        //清除事件回调中传递的事件参数
                        callArgs = [].concat(args);
                        callArgs.shift();
                    }

                    /*合并事件回调参数*/
                    function mergeArg(d) {
                        isDefined(_result) && (d.result = _result);

                        d.preventDefault = preventDefault;
                        d.stop = st.mergeFn(d.stopPropagation, stopFn);
                        dTrans && dTrans.__mergePArg && dTrans.__mergePArg(d);
                    }

                    /*判断传递的属性值*/
                    function checkPropValue(args) {
                        if (isProp) {
                            if (isDefined(_result))
                                return [_result, oldValue];
                            else
                                args.push(oldValue);
                        }
                        return args;
                    }

                    /*执行后置注入方法*/
                    function fireAfter() {
                        if (_stop) {
                            done();
                            return;
                        }

                        whenFire(fire.call(_target, _name, checkPropValue(callArgs), mergeArg), function(result) {
                            setResult(result);
                            done();
                        })
                    }

                    //执行前置注入方法
                    whenFire(fire.call(_target, _name, checkPropValue(callArgs), mergeArg, trTypes[0]), function(result) {
                        setResult(result);
                        if (_preventDefault) {
                            fireAfter();
                            return;
                        }
                        //传递参数赋值
                        dTrans && isDefined(_result) && (dTrans.result = _result);

                        //执行当前方法
                        whenFire(originFn.apply(_target, checkPropValue(args)), function(result) {
                            if (dTrans && isPromise(result))
                                return;

                            setResult(result);
                            fireAfter();
                        })
                    })

                    if (_done)
                        return _result;

                    defer = st.Deferred();

                    return openPromise(defer, _err);
                }

                //处理属性绑定
                if (isProp) {
                    var index = name.lastIndexOf("."),
                        propName = index > 0 ? name.substring(index + 1) : name,
                        propObj = index > 0 ? st.getObj(_target, name.substring(0, index)) : _target;

                    //属性绑定
                    defineProperty(propObj, propName, {
                        get: function() {
                            return _fnMap[name];
                        },
                        set: bindFn
                    });
                } else //方法绑定
                    st.setObj(_target,_name,bindFn);
            }

            if (roundMode) {
                //加入环绕方法,将原方法置入第一个参数
                _targetFn = _target[_name];
                _target[_name] = function() {
                    var args = sliceArgs(arguments);
                    args.unshift(_targetFn);
                    _fn.apply(self, args);
                }
            } else //非环绕模式下添加触发回调
                find(_name, _type, true).add(trName, _fn, _priority, _mode);

            return _target;
        }

        function fire(name, args, argHandle, type) {
            var tr = find(name, type);
            if (tr)
                return tr.fireWith(this, args, argHandle);
        }

        var prop = {
            /**
                注册手动的触发的Handler
                @event onHandler
                @for attachTrigger
                @param name [string] 手动触发器名称
                @param trName [string] 注册事件方法的名称
                @param fn [function] 注册事件方法
                @param [priority] [number] 权重设置,同PrmiseEvent 
                @param [mode] [string] 加入的事件模式,同PrmiseEvent
                @chainable
                @demo test/base/aop.js [onHandler]
            */
            onHandler: function(name, trName, fn, priority, mode) {
                find(name, null, true).add(trName, fn, priority, mode);
                return this;
            },
            /**
                执行手动触发的Handler
                @method fireHandler
                @for attachTrigger
                @param name [string] 手动触发器名称
                @param args [array] 执行参数数组
                @return [object] 执行结果
            */
            fireHandler: function(name, args) {
                return fire(name, args);
            },
            /**
                注册[后置的]事件方法;注册后置和对象注入
                @event on
                @for attachTrigger
                @param name {string|object} 目标方法或者属性名称;[object]类型时为对象注入
                @param trName {string} 注册事件方法的名称|属性名称;对象注入模式下,会自动拼接成trName-[名称|属性名]-[注入方式]
                @param fn {function|object} 注册事件方法;对象注入模式下,[object]类型才会生效
                @param [priority] [number] 权重设置,同PrmiseEvent 
                @param [mode] [string] 加入的事件模式,同PrmiseEvent
                @chainable
                @demo test/base/aop.js [Bind Child] {基础注入}
                @demo test/base/aop.js [on - object] {对象注入}
                @demo test/base/aop.js [watch prop change cancel] {属性监听}
            */
            on: function(name, trName, fn, priority, mode) {
                if (typeof name === 'object') {
                    st.each(name, function(target, config) {
                        var arr = target.split(' '),
                            fnName = arr[0],
                            type = arr[1] || trTypes[1],
                            tName = trName + '-' + fnName + '-' + type;

                        if (st.isFunction(config))
                            bind(fnName, tName, config, type);
                        else
                            bind(fnName, tName, config.fn, type, config.priority, config.mode);
                    })

                } else
                    bind(name, trName, fn, trTypes[1], priority, mode);
                return this;
            },
            /**
                注册前置的事件方法
                @event onBefore
                @for attachTrigger
                @param name [string] 目标方法或者属性名称
                @param trName [string] 注册事件方法的名称
                @param fn [function] 注册事件方法
                @param [priority] [number] 权重设置,同PrmiseEvent 
                @param [mode] [string] 加入的事件模式,同PrmiseEvent
                @chainable
            */
            onBefore: function(name, trName, fn, priority, mode) {
                return bind(name, trName, fn, trTypes[0], priority, mode)
            },
            /**
                注册环绕触发事件
                @event onRound
                @for attachTrigger
                @param name [string] 目标方法或者属性名称
                @param trName [string] 注册事件方法的名称
                @param fn [function] 注册事件方法
                @chainable
                @demo test/base/aop.js [round mode]
            */
            onRound: function(name, trName, fn) {
                return bind(name, trName, fn, trTypes[2])
            },
            /**
                注册错误捕获事件,当执行reject的时候触发
                @event onError
                @for attachTrigger
                @param name [string] 目标方法或者属性名称
                @param trName [string] 注册事件方法的名称
                @param fn [function] 注册事件方法
                @param [mode] [string] 加入的事件模式,同PrmiseEvent
                @chainable
                @demo test/base/aop.js [onError]
            */
            onError: function(name, trName, fn, mode) {
                return bind(name, trName, fn, trTypes[3], mode)
            },
            /**
                注销注册的后置事件方法
                @method off
                @for attachTrigger
                @param name [string] 目标方法或者属性名称
                @param [trName] [string|array] 注册事件方法的名称:
                        1. 空为清除所有
                        2. 字符串为单个
                        3. 数组为多个
                @chainable
                @demo test/base/aop.js [offBefore && off]
            */
            off: function(name, trName) {
                remove(name, trTypes[1], trName);
                return _target;
            },
            /**
                注销注册的前置事件方法
                @method offBefore
                @for attachTrigger
                @param name [string] 目标方法或者属性名称
                @param [trName] [string|array] 注册事件方法的名称:
                        1. 空为清除所有
                        2. 字符串为单个
                        3. 数组为多个
                @chainable
            */
            offBefore: function(name, trName) {
                remove(name, trTypes[0], trName);
                return _target;
            },
            /**
                扩展对象;(在使用触发器注册后,原始方法不会直接在目标对象下,因此使用obj.test = xx的方式来扩展会替换到所有的注册事件)
                @method extend
                @for attachTrigger
                @param prop [object] 目标方法或者属性名称
                @chainable
                @demo test/base/aop.js [extend]
            */
            extend: function(prop) {
                var fn;
                st.each(prop, function(n, p) {
                    ((fn = _fnMap[n]) ? _fnMap : _target)[n] = p;
                })
                return _target;
            }
        };

        applyInterface(target, fnInterface, prop);
        return target;
    }

    /* 应用接口 */
    function applyInterface(target, fnInterface, prop) {
        var fn;

        fnInterface = fnInterface ? st.mergeObj(st.copy(_interface),fnInterface) : _interface;

        st.each(fnInterface, function(i, n) {
            if (n && (fn = prop[i])) {
                target[n] = fn;
            }
        })
    }

    /**
        流程或者生命周期管理器。控制流程的走向,流程扩展,注入控制等等;FlowController是基于trigger封装,具有所有trigger的特性;
        @class flowController
        @constructor
        @param op {object} 参数设置 : 
            @param op.flow {object} 流程对象
            @param [op.order] {array} 流程顺序
            @param [op.trigger] {bool|object} trigger设置
                @param [op.trigger.mode] {object} trigger的mode设置
                @param [op.trigger.iFace] {object} trigger的接口方法设置
            @param [op.mode] {object} 流程的模式, 
            1. 默认为EventArg模式
            2. 'simple', 简单模式不带流程中不带EventArg参数

        @return {flowController} 返回流程控制器
        @demo test/base/aop.js [boot] {基础使用}
        @demo test/base/aop.js [simple Mode] {简单模式}
        @demo test/base/aop.js [promise] {promise示例}
        @demo test/base/aop.js [trigger - end] {promise示例2}
        @demo test/base/aop.js [trigger] {trigger示例}
        @demo test/base/aop.js [trigger - callback mode & interface change] {trigger示例2}
        @demo test/base/aop.js [trigger - transfer Result] {值传递}
    */
    function flowController(op) {
        var flow, order, trigger, mode;
        if (!op)
            return;

        flow = op.flow;
        order = op.order;
        trigger = op.trigger;
        mode = op.mode;

        trigger && attachTrigger(flow, trigger.mode, trigger.iFace);

        /**
         * 已手动设定流程开始的节点启动流程
         * @method bootWithStart
         * @for flowController
         * @param  {string} start 流程开始的节点
         * @param  {array} args  执行参数
         * @return {object|promise} 返回执行结果或者promise(异步)
         * @demo test/base/aop.js [boot with start]
         */
        function bootWithStart(start, args) {
            var _next = start,
                _nextArgs, _done,
                i = -1,
                _result,
                d, _args, originalArgs,
                _stop, defer, _err;

            if (mode !== "simple") {
                /**
                    flowController下的事件参数,由EventArg(trigger)扩展而来,具有EventArg(trigger)的所有特性;
                    其中stop方法为结束当前流程节点;
                    @class EventArg(flowController)
                    @extends EventArg(trigger)
                */
                d = buildPromiseArg({
                    /**
                       结束流程。无论是注册的事件方法还是流程方法全部结束
                       @method end
                       @chainable
                       @demo test/base/aop.js [end]
                     */
                    end: function() {
                        _stop = true;
                        return this;
                    },
                    resolve: function(result) {
                        isDefined(result) && (_result = result);
                        _stop ? done() : next();
                    },
                    /**
                     * 拒绝契约同时设置流程状态为失败,结束流程
                     * @method reject
                     * @param {object} comment 拒绝的说明或参数
                     * @demo test/base/aop.js [reject]
                     */
                    reject: function(comment) {
                        fail(comment);
                    },
                    /**
                       手动指定下一个流程,(指定的流程可以不在order配置中)
                       @method next
                       @param  {string}   nextNode 下一个流程名称
                       @param  {number}   pass     下个流程执行完毕略过的流程数(相对于order)
                       @param  {array}   args     下个流程的参数,只在该流程节点有效,在之后就会恢复成原始参数,如想改变后续参数,请使用changeArgs方法
                       @chainable
                       @demo test/base/aop.js [next]
                     */
                    next: function(nextNode, pass, args) {
                        _next = nextNode;
                        if (typeof pass !== "number")
                            args = pass;
                        else
                            i += pass;

                        args && (_nextArgs = [d].concat(args));
                        return this;
                    },
                    /**
                       改变后续流程的执行参数
                       @method changeArgs
                       @param  {array}   args   执行参数
                       @demo test/base/aop.js [changeArg & originalArgs] {changeArg}
                     */
                    changeArgs: getArgs,
                    /**
                     * 恢复原始执行参数,下个流程中生效,与changeArgs方法对应
                     * @method recoverArgs
                     * @chainable
                     * @demo test/base/aop.js [changeArg & originalArgs] {recoverArgs}
                     */
                    recoverArgs: function() {
                        _args = originalArgs;
                        return this;
                    },
                    __mergePArg: function(arg) {
                        st.mix(arg, d);
                        arg.end = st.mergeFn(arg.stop, arg.end);
                    }
                });
            }

            function getArgs(args, addPromiseArg) {
                _args = d && addPromiseArg !== false ? (args ? [d].concat(args) : [d]) : args;
                return _args;
            }

            originalArgs = getArgs(args);

            function done() {
                _done = true;
                defer && defer.resolve(_result);
            }

            function fail(err) {
                _err = err;
                defer && defer.reject(err);
            }

            function setResult(result) {
                isDefined(result) && (_result = result);
            }

            function next() {
                var index, fnNode, fireArgs;
                if (_stop) {
                    done();
                    return;
                }

                if (_next) {
                    var index = order.indexOf(_next);
                    if (index > -1)
                        i = index;
                } else
                    _next = order[++i];

                isDefined(_result) && (d.result = _result);

                if (_next && (fnNode = flow[_next])) {
                    fireArgs = _nextArgs || _args;
                    _next = _nextArgs = null;
                    st.when(fnNode.apply(flow, fireArgs)).then(function(result) {
                        if (!isPromise(result)) {
                            isDefined(result) && (_result = result);
                            next();
                        }

                    }, fail);
                } else {
                    done();
                    return;
                }
            }

            next();

            if (_done)
                return _result;

            defer = st.Deferred();
            return openPromise(defer, _err);
        }

        /**
         * 启动流程,
         * @method boot
         * @for flowController
         * @param {argument} 流程参数
         * @return {object|promise} 返回执行结果或者promise(异步)
         */
        flow.boot = function() {
            return bootWithStart(null, sliceArgs(arguments));
        }

        flow.bootWithStart = bootWithStart;
        return flow;
    }

    return {
        promiseEvent: promiseEvent,
        attachTrigger: attachTrigger,
        flowController: flowController
    };
});
    
Top