/**
@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 {NodePatches} from './patches/Node.js';
import {OutsideDescriptors, InsideDescriptors} from './patch-instances.js';
import {ParentNodePatches} from './patches/ParentNode.js';
import {DocumentOrFragmentPatches} from './patches/DocumentOrFragment.js';
import {DocumentOrShadowRootPatches} from './patches/DocumentOrShadowRoot.js';
import {ElementOrShadowRootPatches} from './patches/ElementOrShadowRoot.js';
import {ShadowRootPatches} from './patches/ShadowRoot.js';

const patchShadyAccessors = (proto, prefix) => {
  utils.patchProperties(proto,
    utils.getOwnPropertyDescriptors(ShadowRootPatches), true, prefix);
  utils.patchProperties(proto,
    utils.getOwnPropertyDescriptors(DocumentOrShadowRootPatches), true, prefix);
  utils.patchProperties(proto,
    utils.getOwnPropertyDescriptors(ElementOrShadowRootPatches), true, prefix);
  // we ensure ParentNode accessors since these do not exist in Edge/IE on DocumentFragments
  utils.patchProperties(proto,
    utils.getOwnPropertyDescriptors(ParentNodePatches), true, prefix);
  // Ensure `shadowRoot` has basic descriptors when we cannot rely
  // on them coming from DocumentFragment.
  // noPatching case: ensure all Node descriptors are on ShadowRoot
  if (utils.settings.noPatch) {
    utils.patchProperties(proto,
      utils.getOwnPropertyDescriptors(NodePatches), true, prefix);
    utils.patchProperties(proto,
      utils.getOwnPropertyDescriptors(DocumentOrFragmentPatches), true, prefix);
  // bad descriptors case: ensure only accessors are on ShadowRoot.
  } else if (!utils.settings.hasDescriptors) {
    utils.patchProperties(proto, OutsideDescriptors, true);
    utils.patchProperties(proto, InsideDescriptors, true);
  }
}

export const patchShadyRoot = (proto) => {
  proto.__proto__ = DocumentFragment.prototype;

  // patch both prefixed and not, even when noPatch == true.
  patchShadyAccessors(proto, utils.SHADY_PREFIX);
  patchShadyAccessors(proto);

  // Ensure native properties are all safely wrapped since ShadowRoot is not an
  // actual DocumentFragment instance.
  Object.defineProperties(proto, {
    nodeType: {
      value: Node.DOCUMENT_FRAGMENT_NODE,
      configurable: true
    },
    nodeName: {
      value: '#document-fragment',
      configurable: true
    },
    nodeValue: {
      value: null,
      configurable: true
    }
  });

  // make undefined
  [
    'localName',
    'namespaceURI',
    'prefix'
  ].forEach((prop) => {
    Object.defineProperty(proto, prop, {
      value: undefined,
      configurable: true
    });
  });

  // defer properties to host
  [
    'ownerDocument',
    'baseURI',
    'isConnected'
  ].forEach((prop) => {
    Object.defineProperty(proto, prop, {
      get() {
        return this.host[prop];
      },
      configurable: true
    });
  });
}
@@ -1394,17 +1394,17 @@
 );%0A  // 
-w
+W
 e ensure
@@ -1481,16 +1481,17 @@
 ragments
+.
 %0A  utils
@@ -1699,16 +1699,29 @@
 nt.%0A  //
+%0A  // Case 1,
  noPatch
@@ -1727,54 +1727,236 @@
 hing
- 
+: Be
 ca
+u
 se
-: ensure all Node descriptors are
+ we want noPatch ShadyRoots to have native property%0A  // names so that they do not have to be wrapped...%0A  // When we do *not* patch Node/DocumentFragment.prototype%0A  // we must manually install those properties
  on Shad
 owRo
@@ -1951,22 +1951,192 @@
  on Shad
-ow
+y
 Root
+'s prototype.%0A  // Note, it's important to only install these in this mode so as not to stomp%0A  // over CustomElements polyfill's patches on Node/DocumentFragment methods.
 %0A  if (u
@@ -2156,16 +2156,27 @@
 .noPatch
+ && !prefix
 ) %7B%0A    
@@ -2389,16 +2389,24 @@
 x);%0A  //
+ Case 2,
  bad des
@@ -2417,54 +2417,186 @@
 tors
- case: ensure only accessors are on ShadowRoot
+: Ensure accessors are on ShadowRoot.%0A  // These descriptors are normally used for instance patching but because%0A  // ShadyRoot can always be patched, just do it to the prototype
 .%0A  

Update comments aobut how/when to patch properties of ShadyRoot