import {Transform} from 'vega-dataflow';
import {inherits, falsy} from 'vega-util';

/**
 * Invokes encoding functions for visual items.
 * @constructor
 * @param {object} params - The parameters to the encoding functions. This
 *   parameter object will be passed through to all invoked encoding functions.
 * @param {object} param.encoders - The encoding functions
 * @param {function(object, object): boolean} [param.encoders.update] - Update encoding set
 * @param {function(object, object): boolean} [param.encoders.enter] - Enter encoding set
 * @param {function(object, object): boolean} [param.encoders.exit] - Exit encoding set
 */
export default function Encode(params) {
  Transform.call(this, null, params);
}

var prototype = inherits(Encode, Transform);

prototype.transform = function(_, pulse) {
  var out = pulse.fork(pulse.ADD_REM),
      update = _.encoders.update || falsy,
      enter = _.encoders.enter || falsy,
      exit = _.encoders.exit || falsy,
      set = (pulse.encode ? _.encoders[pulse.encode] : update) || falsy;

  if (enter !== falsy || update !== falsy) {
    pulse.visit(pulse.ADD, function(t) {
      enter(t, _);
      update(t, _);
      if (set !== falsy && set !== update) set(t, _);
    });
  }

  if (exit !== falsy) {
    pulse.visit(pulse.REM, function(t) {
      exit(t, _);
    });
  }

  if (set !== falsy) {
    var flag = pulse.MOD | (_.modified() ? pulse.REFLOW : 0);
    pulse.visit(flag, function(t) {
      if (set(t, _)) { out.mod.push(t); }
    });
  }

  return out;
};

@@ -844,16 +844,81 @@
 D_REM),%0A
+      encode = pulse.encode,%0A      reenter = encode === 'enter',%0A
       up
@@ -948,24 +948,24 @@
 e %7C%7C falsy,%0A
-
       enter 
@@ -1049,21 +1049,27 @@
  = (
-pulse.
 encode 
+&& !reenter 
 ? _.
@@ -1077,22 +1077,16 @@
 ncoders%5B
-pulse.
 encode%5D 
@@ -1396,24 +1396,35 @@
 %0A  %7D%0A%0A  if (
+reenter %7C%7C 
 set !== fals
@@ -1511,16 +1511,32 @@
 it(flag,
+ reenter%0A      ?
  functio
@@ -1544,24 +1544,142 @@
 (t) %7B%0A      
+    var mod = enter(t, _);%0A          if (set(t, _) %7C%7C mod) out.mod.push(t);%0A        %7D%0A      : function(t) %7B%0A          
 if (set(t, _
@@ -1680,18 +1680,16 @@
 t(t, _))
- %7B
  out.mod
@@ -1701,16 +1701,23 @@
 (t);
+%0A       
  %7D%0A    
-%7D
 );%0A 

Enable encode re-enter.