pulp.Modules.morph = false;

(function() {
  
  var $p = pulp.base;
  
  var self = pulp.morph = {
    _getOptions: function(duration, onComplete) {
      if (typeof duration == 'function') {
        onComplete = duration;
        duration = null;
      }
      return {
        duration: self._toMs(duration, 1000),
        onComplete: onComplete || pulp.EmptyFunction,
        interval: self.interval
      };
    },
    interval: 34,
    _toMs: function(dur, def) {
      return (dur ? (dur < self.interval ? dur * 1000 : dur) : def);
    },
    _fade: function(start, end, duration, onComplete) {
      this.setStyle('opacity', start);
      self._play.call(this.raw, ['opacity:' + start, 'opacity:' + end], self._getOptions(duration, onComplete));      
    },
    _processStyle: function(s) {
      if (typeof s != 'string') {
        s = pulp.node.styleObjectToString(s);
      }
      if (s.indexOf(':') > -1) {
        // a style string
        s = self._expandShortcuts(s);
      }
      else {
        // class name string
        s = s.replace((/^\./), '');  
      }
      return s;
    },
    _expandShortcuts: function(style) {
      $p.each(self.shortcuts, function(fr) {
        style = style.replace(fr[0], fr[1]);
      });
      return style;
    },
    shortcuts: [
      [(/black/ig), '#000000'],
      [(/gray/ig), '#808080'],
      [(/silver/ig), '#C0C0C0'],
      [(/white/ig), '#FFFFFF'],
      [(/red/ig), '#FF0000'],
      [(/yellow/ig), '#FFFF00'],
      [(/blue/ig), '#0000FF'],
      [(/orange/ig), '#FFA500'],
      [(/green/ig), '#008000'],
      [(/purple/ig), '#800080'],
      [(/maroon/ig), '#800000'],
      [(/fuchsia/ig), '#FF00FF'],
      [(/lime/ig), '#00FF00'],
      [(/olive/ig), '#808000'],
      [(/navy/ig), '#000080'],
      [(/teal/ig), '#008080'],
      [(/aqua/ig), '#00FFFF'],
      [(/cyan/ig), '#00FFFF'],
      [(/border(-top|-right|-bottom|-left)?\s*\:\s*(\+?[\d]+(?:\.d+)?(?:%|[a-z]{2})|0)\s+([a-z]+)\s+#([a-f0-9]{6}|[a-f0-9]{3})/ig), 'border$1-width:$2;border$1-style:$3;border$1-color:#$4'],
      [(/border(-top|-right|-bottom|-left)?\s*\:\s*none/ig), 'border$1-width:0'],
      [(/(padding|margin)\s*\:\s*(\+?[\d]+(?:\.d+)?(?:%|[a-z]{2})|0)\s+(\+?[\d]+(?:\.d+)?(?:%|[a-z]{2})|0)\s+(\+?[\d]+(?:\.d+)?(?:%|[a-z]{2})|0)\s+(\+?[\d]+(?:\.d+)?(?:%|[a-z]{2})|0)/ig), '$1-top:$2;$1-right:$3;$1-bottom:$4;$1-left:$5'],
      [(/(padding|margin)\s*\:\s*(\+?[\d]+(?:\.d+)?(?:%|[a-z]{2})|0)\s+(\+?[\d]+(?:\.d+)?(?:%|[a-z]{2})|0)\s+(\+?[\d]+(?:\.d+)?(?:%|[a-z]{2})|0)/ig), '$1-top:$2;$1-right:$3;$1-bottom:$4;$1-left:$3'],
      [(/(padding|margin)\s*\:\s*(\+?[\d]+(?:\.d+)?(?:%|[a-z]{2})|0)\s+(\+?[\d]+(?:\.d+)?(?:%|[a-z]{2})|0)/ig), '$1-top:$2;$1-right:$3;$1-bottom:$2;$1-left:$3'],
      [(/(padding|margin)\s*\:\s*(\+?[\d]+(?:\.d+)?(?:%|[a-z]{2})|0)/ig), '$1-top:$2;$1-right:$2;$1-bottom:$2;$1-left:$2']
      // TODO: add background shortcut
      // TODO: background and background-position
    ],
    _play: function(tx, opt) {
      var me = this, old = opt.onComplete, anim;
      if (me._pulp_morph_running) {
        window.setTimeout(function() {
          self._play.call(me, tx, opt);
        }, self.interval);
        return;
      }
      opt.onComplete = function() {
        me._pulp_morph_running = false;
        old.call(anim);
      };
      me._pulp_morph_running = true;
      anim = Animator.apply(me, tx, opt).play();
    }
  };
  
  pulp.node.extendPrototype({    
    fadeIn: function(duration, onComplete) {
      self._fade.call(this, 0, 1, duration, onComplete);
      return this;      
    },
    fadeOut: function(duration, onComplete) {
      self._fade.call(this, 1, 0, duration, onComplete);
      return this;      
    },
    fadeInOut: function(delay, onComplete) {
      if (typeof delay == 'function') {
        onComplete = delay;
        delay = null;
      }
      var me = this;
      self._fade.call(this, 0, 1, 400, function() {
        window.setTimeout(function() {
          self._fade.call(me, 1, 0, 2000, onComplete);
        }, self._toMs(parseFloat(delay), 5000));
      });
      return this;      
    },
    morph: function(start, end, duration, onComplete) {
      start = self._processStyle(start);      
      if (!end || typeof end == 'number') {
        self._play.call(this.raw, start, self._getOptions(end, duration));
      }
      else {
        end = self._processStyle(end);      
        this.setStyle(start);
        self._play.call(this.raw, [start, end], self._getOptions(duration, onComplete));
      }
      return this;
    }
  });

})();
