/**
@license
Copyright (c) 2016 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
*/

import * as utils from '../utils.js';
import {shadyDataForNode} from '../shady-data.js';
import {addEventListener, removeEventListener} from '../patch-events.js';

export const SlotPatches = utils.getOwnPropertyDescriptors({

  /**
   * @this {HTMLSlotElement}
   * @param {Object=} options
   */
  assignedNodes(options) {
    if (this.localName === 'slot') {
      // Force any containing shadowRoot to flush so that distribution occurs
      // and this node has assignedNodes.
      const root = this[utils.SHADY_PREFIX + 'getRootNode']();
      if (root && utils.isShadyRoot(root)) {
        root._render();
      }
      const nodeData = shadyDataForNode(this);
      return nodeData ?
        ((options && options.flatten ? nodeData.flattenedNodes :
          nodeData.assignedNodes) || []) :
        [];
    }
  },

  /**
   * @this {HTMLSlotElement}
   * @param {string} type
   * @param {Function} fn
   * @param {Object|boolean=} optionsOrCapture
   */
  addEventListener(type, fn, optionsOrCapture) {
    if (typeof optionsOrCapture !== 'object') {
      optionsOrCapture = {
        capture: Boolean(optionsOrCapture)
      }
    }
    if (type === 'slotchange') {
      addEventListener.call(this, type, fn, optionsOrCapture);
    } else {
      const parent = this[utils.SHADY_PREFIX + 'parentNode'];
      if (!parent) {
        throw new Error('ShadyDOM cannot attach event to slot unless it has a `parentNode`');
      }
      optionsOrCapture.__shadyTarget = this;
      parent[utils.SHADY_PREFIX + 'addEventListener'](type, fn, optionsOrCapture);
    }
  },

  /**
   * @this {HTMLSlotElement}
   * @param {string} type
   * @param {Function} fn
   * @param {Object|boolean=} optionsOrCapture
   */
  removeEventListener(type, fn, optionsOrCapture) {
    if (typeof optionsOrCapture !== 'object') {
      optionsOrCapture = {
        capture: Boolean(optionsOrCapture)
      }
    }
    if (type === 'slotchange') {
      removeEventListener.call(this, type, fn, optionsOrCapture);
    } else {
      const parent = this[utils.SHADY_PREFIX + 'parentNode'];
      if (!parent) {
        throw new Error('ShadyDOM cannot attach event to slot unless it has a `parentNode`');
      }
      optionsOrCapture.__shadyTarget = this;
      parent[utils.SHADY_PREFIX + 'removeEventListener'](type, fn, optionsOrCapture);
    }
  }

});

@@ -1646,36 +1646,193 @@
     %7D%0A    %7D%0A    
-if (
+// NOTE, check if this is a %60slot%60 because these patches are installed on%0A    // Element where browsers don't have %60%3Cslot%3E%60%0A    if (this.localName !== 'slot' %7C%7C 
 type === 'slotch
@@ -2565,28 +2565,185 @@
 %7D%0A    %7D%0A    
-if (
+// NOTE, check if this is a %60slot%60 because these patches are installed on%0A    // Element where browsers don't have %60%3Cslot%3E%60%0A    if (this.localName !== 'slot' %7C%7C 
 type === 'sl

Fix patch to work on browsers that don't have `<slot>` element