/*
 * Copyright (C) 2007-2018 Diego Perini
 * All rights reserved.
 *
 * Caching/memoization module for NWMatcher
 *
 * Added capabilities:
 *
 * - Mutation Events are feature tested and used safely
 * - handle caching different document types HTML/XML/SVG
 * - store result sets for different selectors / contexts
 * - simultaneously control mutation on multiple documents
 *
 */

(function(global) {

  // export the public API for CommonJS implementations,
  // for headless JS engines or for standard web browsers
  var Dom =
    // as CommonJS/NodeJS module
    typeof exports == 'object' ? exports :
    // create or extend NW namespace
    ((global.NW || (global.NW = { })) &&
    (global.NW.Dom || (global.NW.Dom = { }))),

  Contexts = { },
  Results = { },

  isEnabled = false,
  isExpired = true,
  isPaused = false,

  context = global.document,
  root = context.documentElement,

  // timing pauses
  now = 0,

  // last time cache initialization was called
  lastCalled = 0,

  // minimum time allowed between calls to the cache initialization
  minCacheRest = 15, //ms

  mutationTest =
    function(type, callback) {
      var isSupported = false,
      root = document.documentElement,
      div = document.createElement('div'),
      handler = function() { isSupported = true; };
      root.insertBefore(div, root.firstChild);
      div.addEventListener(type, handler, true);
      if (callback && callback.call) callback(div);
      div.removeEventListener(type, handler, true);
      root.removeChild(div);
      return isSupported;
    },

  // check for Mutation Events, DOMAttrModified should be
  // enough to ensure DOMNodeInserted/DOMNodeRemoved exist
  HACKED_MUTATION_EVENTS = false,

  NATIVE_MUTATION_EVENTS = root.addEventListener ?
    mutationTest('DOMAttrModified', function(e) { e.setAttribute('id', 'nw'); }) : false,

  loadResults =
    function(selector, from, doc, root) {
      if (isEnabled && !isPaused) {
        if (!isExpired) {
          if (Results[selector] && Contexts[selector] === from) {
            return Results[selector];
          }
        } else {
          // pause caching while we are getting
          // hammered by dom mutations (jdalton)
          now = (new Date).getTime();
          if ((now - lastCalled) < minCacheRest) {
            isPaused = isExpired = true;
            setTimeout(function() { isPaused = false; }, minCacheRest);
          } else setCache(true, doc);
          lastCalled = now;
        }
      }
      return undefined;
    },

  saveResults =
    function(selector, from, doc, data) {
      Contexts[selector] = from;
      Results[selector] = data;
      return;
    },

  /*-------------------------------- CACHING ---------------------------------*/

  // invoked by mutation events to expire cached parts
  mutationWrapper =
    function(event) {
      var d = event.target.ownerDocument || event.target;
      stopMutation(d);
      expireCache(d);
    },

  // append mutation events
  startMutation =
    function(d) {
      if (!d.isCaching && d.addEventListener) {
        // FireFox/Opera/Safari/KHTML have support for Mutation Events
        d.addEventListener('DOMAttrModified', mutationWrapper, true);
        d.addEventListener('DOMNodeInserted', mutationWrapper, true);
        d.addEventListener('DOMNodeRemoved',  mutationWrapper, true);
        d.isCaching = true;
      }
    },

  // remove mutation events
  stopMutation =
    function(d) {
      if (d.isCaching && d.removeEventListener) {
        d.removeEventListener('DOMAttrModified', mutationWrapper, true);
        d.removeEventListener('DOMNodeInserted', mutationWrapper, true);
        d.removeEventListener('DOMNodeRemoved',  mutationWrapper, true);
        d.isCaching = false;
      }
    },

  // enable/disable context caching system
  // @d optional document context (iframe, xml document)
  // script loading context will be used as default context
  setCache =
    function(enable, d) {
      if (!!enable) {
        isExpired = false;
        startMutation(d);
      } else {
        isExpired = true;
        stopMutation(d);
      }
      isEnabled = !!enable;
    },

  // expire complete cache
  // can be invoked by Mutation Events or
  // programmatically by other code/scripts
  // document context is mandatory no checks
  expireCache =
    function(d) {
      isExpired = true;
      Contexts = { };
      Results = { };
    };

  if (!NATIVE_MUTATION_EVENTS && root.addEventListener && Element && Element.prototype) {
    if (mutationTest('DOMNodeInserted', function(e) { e.appendChild(document.createElement('div')); }) &&
        mutationTest('DOMNodeRemoved', function(e) { e.removeChild(e.appendChild(document.createElement('div'))); })) {
      HACKED_MUTATION_EVENTS = true;
      Element.prototype._setAttribute = Element.prototype.setAttribute;
      Element.prototype.setAttribute =
        function(name, val) {
          this._setAttribute(name, val);
          mutationWrapper({
            target: this,
            type: 'DOMAttrModified',
            attrName: name,
            attrValue: val });
        };
    }
  }

  isEnabled = NATIVE_MUTATION_EVENTS || HACKED_MUTATION_EVENTS;

  /*------------------------------- PUBLIC API -------------------------------*/

  // save results into cache
  Dom.saveResults = saveResults;

  // load results from cache
  Dom.loadResults = loadResults;

  // expire DOM tree cache
  Dom.expireCache = expireCache;

  // enable/disable cache
  Dom.setCache = setCache;

})(this);
