text: 'use strict';
  /* global ComponentUtils */
  
  window.GaiaRadio = (function(win) {
    // Extend from the HTMLElement prototype
    var proto = Object.create(HTMLElement.prototype);
  
    // Allow baseurl to be overridden (used for demo page)
    var baseurl = window.GaiaRadioBaseurl ||
      '../shared/elements/gaia_radio/';
  
    proto.createdCallback = function() {
      var shadow = this.createShadowRoot();
      this._template = template.content.cloneNode(true);
  
      this._wrapper = this._template.getElementById('radio');
      this._wrapper.addEventListener('click', this.handleClick.bind(this));
      this.addEventListener('keyup', this.handleKeyUp.bind(this));
  
      // The default 'radio' accessibility role could be overridden.
      if (this.dataset.role) {
        this._wrapper.setAttribute('role', this.dataset.role);
      }
  
      if (!this.hasAttribute('role')) {
        // The root element has no accessibility use, purge it from the tree.
        this.setAttribute('role', 'presentation');
      }
  
      this.configureClass();
  
      shadow.appendChild(this._template);
  
      this.checked = this.hasAttribute('checked');
      this._wrapper.setAttribute('aria-checked', this.checked);
  
      // When events are triggered on content nodes, they do not bubble to
      // our custom element. We add an event listener on our children so we can
      // intercept the click and, process the state change, and notify listeners.
      // Platform bug 887541.
      setTimeout(function nextTick() {
        var label = this.querySelector('label, p');
        if (!label) {
          return;
        }
        label.addEventListener('click', this.handleClick.bind(this));
      }.bind(this));
  
      ComponentUtils.style.call(this, baseurl);
  
      // Proxy RTL changes to the shadow root so we can style for RTL.
      var dirObserver = new MutationObserver(this.updateInternalDir.bind(this));
      dirObserver.observe(document.documentElement, {
        attributeFilter: ['dir'],
        attributes: true
      });
      this.updateInternalDir();
    };
  
    proto.updateInternalDir = function() {
      var internal = this.shadowRoot.firstElementChild;
      if (document.documentElement.dir === 'rtl') {
        internal.setAttribute('dir', 'rtl');
      } else {
        internal.removeAttribute('dir');
      }
    };
  
    /**
     * Handles a key event on the shadow dom.
     * handleClick will be invoked only when pressing Enter key.
     */
    proto.handleKeyUp = function(e) {
      switch(e.keyCode){
        case 13: // Enter key
          this.handleClick(e);
          break;
      }
    };
  
    /**
     * Handles a click event on the shadow dom.
     * We handle checking/unchecking of radio elements and proxy the click
     * event to any click listeners on the gaia-radio. This is a nice transition
     * that preserves backwards behavior and should make it easier to port apps.
     */
    proto.handleClick = function(e) {
      // We add this event listener twice (see above) on both the content and
      // custom element nodes. We need to stop the event propagation to prevent
      // this event from firing against both nodes.
      e.stopImmediatePropagation();
  
      // Dispatch a click event to any listeners to the app.
      // We should be able to remove this when bug 887541 lands.
      var event = new MouseEvent('click', {
        view: window,
        bubbles: true,
        cancelable: true
      });
      this.dispatchEvent(event);
  
      // If this radio component is already checked, don't do anything.
      if (this.checked) {
        return;
      }
  
      if (!event.defaultPrevented) {
        this.checked = !this.checked;
      }
  
      // Dispatch a change event for the gaia-switch.
      this.dispatchEvent(new CustomEvent('change', {
        bubbles: true,
        cancelable: false
      }));
    };
  
    /**
     * Configures the class for the element.
     */
    proto.configureClass = function() {
      this._wrapper.className = this.className;
      this._wrapper.classList.toggle('checked', this._checked);
    };
  
    /**
     * Helper method to remove the component details.
     */
    proto.hideDetails = function() {
      this.shadowRoot.querySelector('.details').style.display = 'none';
    };
  
    /**
     * Proxy className property to the wrapper.
     */
    proto.attributeChangedCallback = function(name, from, to) {
      if (name === 'class') {
        this._wrapper.className = to;
      }
    };
  
    /**
     * Handle setting/getting of the checked property.
     */
    Object.defineProperty(proto, 'checked', {
      get: function() {
        return this._checked;
      },
      set: function(value) {
        // Return early if we have not initialized.
        // In some cases a radio of the same name might try to toggle this one
        // before we've run the createdCallback.
        if (!this._template) {
          return;
        }
        if (value) {
          // Uncheck other radio elements with the same name and check this one.
          var relevant = document.querySelectorAll(
            'gaia-radio[name="' + this.getAttribute('name') + '"]');
          for (var i = 0, iLen = relevant.length; i < iLen; i++) {
            relevant[i].checked = false;
          }
          this.setAttribute('checked', true);
        } else {
          this.removeAttribute('checked');
        }
        this._wrapper.classList.toggle('checked', value);
        this._wrapper.setAttribute('aria-checked', value);
        this._checked = value;
      }
    });
  
    /**
     * Proxy the name property to the input element.
     */
    Object.defineProperty( proto, 'name', {
      get: function() {
        return this.getAttribute('name');
      },
      set: function(value) {
        this.setAttribute('name', value);
      }
    });
  
    /**
     * Proxy the value property to the input element.
     */
    Object.defineProperty( proto, 'value', {
      get: function() {
        return this.getAttribute('value');
      },
      set: function(value) {
        this.setAttribute('value', value);
      }
    });
  
    /**
     * Proxy the input type.
     */
    Object.defineProperty( proto, 'type', {
      get: function() {
        return 'gaia-radio';
      }
    });
  
    // Handle both p and label elements for now to support existing
    // building blocks. Mainly radio labels and inputs inside a list
    // as this is a rather common use case.
    var template = document.createElement('template');
    template.innerHTML = '<span role="radio" id="radio">' +
        '<span><content select="p,label"></content></span>' +
        '<div class="details"><content select="details"></content></div>' +
        '<div class="divider"></div>' +
      '</span>';
  
    // Register and return the constructor
    return document.registerElement('gaia-radio', { prototype: proto });
  })(window);
  