import t from 'tcomb';
import isReactComponent from '../isReactComponent';
import debug from 'debug';

const log = debug('revenge:@pure');

function shallowEqual(objA, objB, section, component) {
  if (objA === objB) {
    return true;
  }
  const displayName = component.constructor.name;
  const rootNodeID = component._reactInternalInstance._rootNodeID;
  let key;
  // Test for A's keys different from B.
  for (key in objA) {
    if (objA.hasOwnProperty(key) &&
        (!objB.hasOwnProperty(key) || objA[key] !== objB[key])) {
      if (process.env.NODE_ENV !== 'production') {
        log(`component ${displayName} with rootNodeID ${rootNodeID} will re-render since ${section} key ${key} is changed from `, objA[key], ' to ', objB[key]);
      }
      return false;
    }
  }
  // Test for B's keys missing from A.
  for (key in objB) {
    if (objB.hasOwnProperty(key) && !objA.hasOwnProperty(key)) {
      if (process.env.NODE_ENV !== 'production') {
        log(`component ${displayName} with rootNodeID ${rootNodeID} will re-render since ${section} key ${key} with value `, objB[key], 'is new');
      }
      return false;
    }
  }
  return true;
}

export default function pure(Component) {

  if (process.env.NODE_ENV !== 'production') {
    t.assert(isReactComponent(Component), `@pure decorator can only be applied to React.Component(s)`);
  }

  const originalScu = Component.prototype.shouldComponentUpdate;

  Component.prototype.shouldComponentUpdate = function(nextProps, nextState) {
    const _scu = () => {
      return !shallowEqual(this.props, nextProps, 'props', this) ||
             !shallowEqual(this.state, nextState, 'state', this);
    };
    return originalScu ? originalScu(nextProps, nextState, _scu) : _scu();
  };
}

@@ -233,16 +233,17 @@
 ue;%0A  %7D%0A
+%0A
   const 
@@ -351,16 +351,414 @@
 NodeID;%0A
+%0A  if (!objA %7C%7C typeof objA !== 'object') %7B%0A    // the opposite should never happen here, since we are using this as%0A    // %60shallowEqual(prevProps, nextProps)%60 or %60shallowEqual(prevState, nextState)%60%0A    if (process.env.NODE_ENV !== 'production') %7B%0A      log(%60component $%7BdisplayName%7D with rootNodeID $%7BrootNodeID%7D will re-render since object has no previous value%60);%0A    %7D%0A    return false;%0A  %7D%0A%0A
   let ke

handle more gracefully a nully objA in shallowEqual