/**
 * @ignore
 * animate on single property
 * @author yiminghe@gmail.com
 */
KISSY.add('anim/timer/fx', function (S, Dom, undefined) {
    var logger = S.getLogger('s/aim/timer/fx');

    function load(self, cfg) {
        S.mix(self, cfg);
        self.pos = 0;
        self.unit = self.unit || '';
    }

    /**
     * basic animation about single css property or element attribute
     * @class KISSY.Anim.Fx
     * @private
     */
    function Fx(cfg) {
        load(this, cfg);
    }

    Fx.prototype = {
        // default to dom anim
        isCustomFx: 0,

        constructor: Fx,

        /**
         * reset config.
         * @param cfg
         */
        load: function (cfg) {
            load(this, cfg);
        },

        /**
         * process current anim frame.
         * @param pos
         */
        frame: function (pos) {
            if (this.pos === 1) {
                return;
            }

            var self = this,
                anim = self.anim,
                prop = self.prop,
                node = anim.node,
                from = self.from,
                propData = self.propData,
                to = self.to;

            if (pos === undefined) {
                pos = getPos(anim, propData);
            }

            self.pos = pos;

            if (from === to || pos === 0) {
                return;
            }

            var val = self.interpolate(from, to, self.pos);

            self.val = val;

            if (propData.frame) {
                propData.frame.call(self, anim, self);
            }
            // in case completed in frame
            else if (!self.isCustomFx) {
                if (val === /**@type Number @ignore*/undefined) {
                    // 插值出错,直接设置为最终值
                    self.pos = 1;
                    val = to;
                    logger.warn(prop + ' update directly ! : ' + val + ' : ' + from + ' : ' + to);
                } else {
                    val += self.unit;
                }
                self.val = val;
                if (isAttr(node, prop)) {
                    Dom.attr(node, prop, val, 1);
                } else {
                    Dom.css(node, prop, val);
                }
            }
        },

        /**
         * interpolate function
         *
         * @param {Number} from current css value
         * @param {Number} to end css value
         * @param {Number} pos current position from easing 0~1
         * @return {Number} value corresponding to position
         */
        interpolate: function (from, to, pos) {
            // 默认只对数字进行 easing
            if ((typeof from === 'number') &&
                (typeof to === 'number')) {
                return /**@type Number @ignore*/Math.round((from + (to - from) * pos) * 1e5) / 1e5;
            } else {
                return /**@type Number @ignore*/undefined;
            }
        },

        /**
         * current value
         *
         */
        cur: function () {
            var self = this,
                prop = self.prop,
                node = self.anim.node;
            //不是css 或者 attribute 的缓动
            if (self.isCustomFx) {
                return node[prop] || 0;
            }
            else if (isAttr(node, prop)) {
                return Dom.attr(node, prop, undefined, 1);
            } else {
                var parsed,
                    r = Dom.css(node, prop);
                // Empty strings, null, undefined and 'auto' are converted to 0,
                // complex values such as 'rotate(1rad)' or '0px 10px' are returned as is,
                // simple values such as '10px' are parsed to Float.
                return isNaN(parsed = parseFloat(r)) ?
                    !r || r === 'auto' ? 0 : r
                    : parsed;
            }
        }
    };

    function isAttr(node, prop) {
        // support scrollTop/Left now!
        if ((!node.style || node.style[ prop ] == null) &&
            Dom.attr(node, prop, undefined, 1) != null) {
            return 1;
        }
        return 0;
    }

    function getPos(anim, propData) {
        var t = S.now(),
            runTime,
            startTime = anim.startTime,
            delay = propData.delay,
            duration = propData.duration;
        runTime = t - startTime - delay;
        if (runTime <= 0) {
            return 0;
        } else if (runTime >= duration) {
            return 1;
        } else {
            return propData.easing(runTime / duration);
        }
    }

    Fx.Factories = {};

    Fx.getFx = function (cfg) {
        var Constructor = Fx,
            SubClass;
        if (!cfg.isCustomFx && (SubClass = Fx.Factories[cfg.prop])) {
            Constructor = SubClass
        }
        return new Constructor(cfg);
    };

    return Fx;
}, {
    requires: ['dom']
});
/*
 TODO
 支持 transform ,ie 使用 matrix
 - http://shawphy.com/2011/01/transformation-matrix-in-front-end.html
 - http://www.cnblogs.com/winter-cn/archive/2010/12/29/1919266.html
 - 标准:http://www.zenelements.com/blog/css3-transform/
 - ie: http://www.useragentman.com/IETransformsTranslator/
 - wiki: http://en.wikipedia.org/wiki/Transformation_matrix
 - jq 插件: http://plugins.jquery.com/project/2d-transform
 */