'use strict';

Object.defineProperty(exports, '__esModule', {
  value: true
});

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

var _eventListenerProps = require('./event-listener-props');

var _eventListenerProps2 = _interopRequireDefault(_eventListenerProps);

exports['default'] = function (domNode, oldVirtualNode, newVirtualNode, options) {
  var oldProps = oldVirtualNode && oldVirtualNode.props;
  var newProps = newVirtualNode.props;

  var refs = undefined,
      listenerContext = undefined;
  if (options) {
    refs = options.refs;
    listenerContext = options.listenerContext;
  }
  updateProps(domNode, oldProps, newProps);
  if (refs) updateRef(domNode, oldProps && oldProps.ref, newProps && newProps.ref, refs);
  updateEventListeners(domNode, oldVirtualNode, newVirtualNode, listenerContext);
};

function updateProps(domNode, oldProps, newProps) {
  if (oldProps) {
    var oldPropsNames = Object.keys(oldProps);
    for (var i = 0; i < oldPropsNames.length; i++) {
      var _name = oldPropsNames[i];
      if (_name === 'ref' || _name === 'on') continue;
      if (_name in _eventListenerProps2['default']) continue;
      if (!newProps || !(_name in newProps)) {
        if (_name === 'dataset') {
          updateProps(domNode.dataset, oldProps ? oldProps.dataset : null, null);
        } else if (_name === 'style') {
          updateProps(domNode.style, oldProps ? oldProps.style : null, null);
        } else {
          delete domNode[_name];
        }
      }
    }
  }

  if (newProps) {
    var newPropsNames = Object.keys(newProps);
    for (var i = 0; i < newPropsNames.length; i++) {
      var _name2 = newPropsNames[i];
      if (_name2 === 'ref' || _name2 === 'on') continue;
      if (_name2 in _eventListenerProps2['default']) continue;
      var oldValue = oldProps && oldProps[_name2];
      var newValue = newProps[_name2];
      if (_name2 === 'dataset') {
        updateProps(domNode.dataset, oldProps ? oldProps.dataset : null, newProps.dataset);
      } else if (_name2 === 'style') {
        updateProps(domNode.style, oldProps ? oldProps.style : null, newProps.style);
      } else {
        if (newValue !== oldValue) {
          domNode[_name2] = newValue;
        }
      }
    }
  }
}

function updateRef(domNode, oldRefName, newRefName, refs) {
  if (newRefName !== oldRefName) {
    if (oldRefName && refs[oldRefName] === domNode) delete refs[oldRefName];
    if (newRefName) refs[newRefName] = domNode;
  }
}

function updateEventListeners(domNode, oldVirtualNode, newVirtualNode, listenerContext) {
  var oldListeners = oldVirtualNode && oldVirtualNode.props && oldVirtualNode.props.on;
  var newListeners = newVirtualNode.props && newVirtualNode.props.on;

  for (var eventName in oldListeners) {
    if (!(newListeners && eventName in newListeners)) {
      var listenerToRemove = undefined;
      if (oldVirtualNode && oldVirtualNode.boundListeners && oldVirtualNode.boundListeners[eventName]) {
        listenerToRemove = oldVirtualNode.boundListeners[eventName];
      } else {
        listenerToRemove = oldListeners[eventName];
      }
      domNode.removeEventListener(eventName, listenerToRemove);
    }
  }

  for (var eventName in newListeners) {
    var oldListener = oldListeners && oldListeners[eventName];
    var newListener = newListeners[eventName];

    if (newListener !== oldListener) {
      if (oldListener) {
        var listenerToRemove = undefined;
        if (oldVirtualNode && oldVirtualNode.boundListeners && oldVirtualNode.boundListeners[eventName]) {
          listenerToRemove = oldVirtualNode.boundListeners[eventName];
        } else {
          listenerToRemove = oldListener;
        }
        domNode.removeEventListener(eventName, listenerToRemove);
      }
      var listenerToAdd = undefined;
      if (listenerContext) {
        listenerToAdd = newListener.bind(listenerContext);
        if (!newVirtualNode.boundListeners) newVirtualNode.boundListeners = {};
        newVirtualNode.boundListeners[eventName] = listenerToAdd;
      } else {
        listenerToAdd = newListener;
      }
      domNode.addEventListener(eventName, listenerToAdd);
    }
  }
}
module.exports = exports['default'];