<!DOCTYPE html>
<!--
Copyright (c) 2014 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->

<polymer-element name="tr-ui-a-tab-view"
    constructor="TracingAnalysisTabView">
  <template>
    <style>
      :host {
        display: flex;
        flex-flow: column nowrap;
        overflow: hidden;
        box-sizing: border-box;
      }

      tab-strip[tabs-hidden] {
        display: none;
      }

      tab-strip {
        background-color: rgb(236, 236, 236);
        border-bottom: 1px solid #8e8e8e;
        display: flex;
        flex: 0 0 auto;
        flex-flow: row;
        overflow-x: auto;
        padding: 0 10px 0 10px;
        font-size: 12px;
      }

      tab-button {
        display: block;
        flex: 0 0 auto;
        padding: 4px 15px 1px 15px;
        margin-top: 2px;
      }

      tab-button[selected=true] {
        background-color: white;
        border: 1px solid rgb(163, 163, 163);
        border-bottom: none;
        padding: 3px 14px 1px 14px;
      }

      tabs-content-container {
        display: flex;
        flex: 1 1 auto;
        overflow: auto;
        width: 100%;
      }

      ::content > * {
        flex: 1 1 auto;
      }

      ::content > *:not([selected]) {
        display: none;
      }

      button-label {
        display: inline;
      }

      tab-strip-heading {
        display: block;
        flex: 0 0 auto;
        padding: 4px 15px 1px 15px;
        margin-top: 2px;
        margin-before: 20px;
        margin-after: 10px;
      }
      #tsh {
        display: inline;
        font-weight: bold;
      }
    </style>

    <tab-strip>
      <tab-strip-heading id="tshh">
        <span id="tsh"></span>
      </tab-strip-heading>
      <template repeat="{{tab in tabs_}}">
        <tab-button
            button-id="{{ tab.id }}"
            on-click="{{ tabButtonSelectHandler_ }}"
            selected="{{ selectedTab_.id === tab.id }}">
          <button-label>{{ tab.label ? tab.label : 'No Label'}}</button-label>
        </tab-button>
      </template>
    </tab-strip>

    <tabs-content-container id='content-container'>
        <content></content>
    </tabs-content-container>

  </template>

  <script>
  'use strict';
  Polymer({
    ready: function() {
      this.$.tshh.style.display = 'none';

      // A tab is represented by the following tuple:
      // (id, label, content, observer, savedScrollTop, savedScrollLeft).
      // The properties are used in the following way:
      // id: Uniquely identifies a tab. It is the same number as the index
      //     in the tabs array. Used primarily by the on-click event attached
      //     to buttons.
      // label: A string, representing the label printed on the tab button.
      // content: The light-dom child representing the contents of the tab.
      //     The content is appended to this tab-view by the user.
      // observers: The observers attached to the content node to watch for
      //     attribute changes. The attributes of interest are: 'selected',
      //     and 'tab-label'.
      // savedScrollTop/Left: Used to return the scroll position upon switching
      //     tabs. The values are generally saved when a tab switch occurs.
      //
      // The order of the tabs is relevant for the tab ordering.
      this.tabs_ = [];
      this.selectedTab_ = undefined;

      // Register any already existing children.
      for (var i = 0; i < this.children.length; i++)
        this.processAddedChild_(this.children[i]);

      // In case the user decides to add more tabs, make sure we watch for
      // any child mutations.
      this.childrenObserver_ = new MutationObserver(
          this.childrenUpdated_.bind(this));
      this.childrenObserver_.observe(this, { childList: 'true' });
    },

    get tabStripHeadingText() {
      return this.$.tsh.textContent;
    },

    set tabStripHeadingText(tabStripHeadingText) {
      this.$.tsh.textContent = tabStripHeadingText;
      if (!!tabStripHeadingText)
        this.$.tshh.style.display = '';
      else
        this.$.tshh.style.display = 'none';
    },

    get selectedTab() {
      // Make sure we process any pending children additions / removals, before
      // trying to select a tab. Otherwise, we might not find some children.
      this.childrenUpdated_(
        this.childrenObserver_.takeRecords(), this.childrenObserver_);

      // Do not give access to the user to the inner data structure.
      // A user should only be able to mutate the added tab content.
      if (this.selectedTab_)
        return this.selectedTab_.content;
      return undefined;
    },

    set selectedTab(content) {
      // Make sure we process any pending children additions / removals, before
      // trying to select a tab. Otherwise, we might not find some children.
      this.childrenUpdated_(
        this.childrenObserver_.takeRecords(), this.childrenObserver_);

      if (content === undefined || content === null) {
        this.changeSelectedTabById_(undefined);
        return;
      }

      // Search for the specific node in our tabs list.
      // If it is not there print a warning.
      var contentTabId = undefined;
      for (var i = 0; i < this.tabs_.length; i++)
        if (this.tabs_[i].content === content) {
          contentTabId = this.tabs_[i].id;
          break;
        }

      if (contentTabId === undefined) {
        console.warn('Tab not in tabs list. Ignoring changed selection.');
        return;
      }

      this.changeSelectedTabById_(contentTabId);
    },

    get tabsHidden() {
      var ts = this.shadowRoot.querySelector('tab-strip');
      return ts.hasAttribute('tabs-hidden');
    },

    set tabsHidden(tabsHidden) {
      tabsHidden = !!tabsHidden;
      var ts = this.shadowRoot.querySelector('tab-strip');
      if (tabsHidden)
        ts.setAttribute('tabs-hidden', true);
      else
        ts.removeAttribute('tabs-hidden');
    },

    get tabs() {
      return this.tabs_.map(function(tabObject) {
        return tabObject.content;
      });
    },

    /**
     * Function called on light-dom child addition.
     */
    processAddedChild_: function(child) {
      var observerAttributeSelected = new MutationObserver(
          this.childAttributesChanged_.bind(this));
      var observerAttributeTabLabel = new MutationObserver(
          this.childAttributesChanged_.bind(this));
      var tabObject = {
        id: this.tabs_.length,
        content: child,
        label: child.getAttribute('tab-label'),
        observers: {
          forAttributeSelected: observerAttributeSelected,
          forAttributeTabLabel: observerAttributeTabLabel
        }
      };

      this.tabs_.push(tabObject);
      if (child.hasAttribute('selected')) {
        // When receiving a child with the selected attribute, if we have no
        // selected tab, mark the child as the selected tab, otherwise keep
        // the previous selection.
        if (this.selectedTab_)
          child.removeAttribute('selected');
        else
          this.setSelectedTabById_(tabObject.id);
      }

      // This is required because the user might have set the selected
      // property before we got to process the child.
      var previousSelected = child.selected;

      var tabView = this;

      Object.defineProperty(
          child,
          'selected', {
            configurable: true,
            set: function(value) {
              if (value) {
                tabView.changeSelectedTabById_(tabObject.id);
                return;
              }

              var wasSelected = tabView.selectedTab_ === tabObject;
              if (wasSelected)
                tabView.changeSelectedTabById_(undefined);
            },
            get: function() {
              return this.hasAttribute('selected');
            }
          });

      if (previousSelected)
        child.selected = previousSelected;

      observerAttributeSelected.observe(child,
          { attributeFilter: ['selected'] });
      observerAttributeTabLabel.observe(child,
          { attributeFilter: ['tab-label'] });

    },

    /**
     * Function called on light-dom child removal.
     */
    processRemovedChild_: function(child) {
      for (var i = 0; i < this.tabs_.length; i++) {
        // Make sure ids are the same as the tab position after removal.
        this.tabs_[i].id = i;
        if (this.tabs_[i].content === child) {
          this.tabs_[i].observers.forAttributeSelected.disconnect();
          this.tabs_[i].observers.forAttributeTabLabel.disconnect();
          // The user has removed the currently selected tab.
          if (this.tabs_[i] === this.selectedTab_) {
            this.clearSelectedTab_();
            this.fire('selected-tab-change');
          }
          child.removeAttribute('selected');
          delete child.selected;
          // Remove the observer since we no longer care about this child.
          this.tabs_.splice(i, 1);
          i--;
        }
      }
    },


    /**
     * This function handles child attribute changes. The only relevant
     * attributes for the tab-view are 'tab-label' and 'selected'.
     */
    childAttributesChanged_: function(mutations, observer) {
      var tabObject = undefined;
      // First figure out which child has been changed.
      for (var i = 0; i < this.tabs_.length; i++) {
        var observers = this.tabs_[i].observers;
        if (observers.forAttributeSelected === observer ||
            observers.forAttributeTabLabel === observer) {
            tabObject = this.tabs_[i];
            break;
        }
      }

      // This should not happen, unless the user has messed with our internal
      // data structure.
      if (!tabObject)
        return;

      // Next handle the attribute changes.
      for (var i = 0; i < mutations.length; i++) {
        var node = tabObject.content;
        // 'tab-label' attribute has been changed.
        if (mutations[i].attributeName === 'tab-label')
          tabObject.label = node.getAttribute('tab-label');
        // 'selected' attribute has been changed.
        if (mutations[i].attributeName === 'selected') {
          // The attribute has been set.
          var nodeIsSelected = node.hasAttribute('selected');
          if (nodeIsSelected)
            this.changeSelectedTabById_(tabObject.id);
          else
            this.changeSelectedTabById_(undefined);
        }
      }
    },

    /**
     * This function handles light-dom additions and removals from the
     * tab-view component.
     */
    childrenUpdated_: function(mutations, observer) {
      mutations.forEach(function(mutation) {
        for (var i = 0; i < mutation.removedNodes.length; i++)
          this.processRemovedChild_(mutation.removedNodes[i]);
        for (var i = 0; i < mutation.addedNodes.length; i++)
          this.processAddedChild_(mutation.addedNodes[i]);
      }, this);
    },

    /**
     * Handler called when a click event happens on any of the tab buttons.
     */
    tabButtonSelectHandler_: function(event, detail, sender) {
      this.changeSelectedTabById_(sender.getAttribute('button-id'));
    },

    /**
     * This does the actual work. :)
     */
    changeSelectedTabById_: function(id) {
      var newTab = id !== undefined ? this.tabs_[id] : undefined;
      var changed = this.selectedTab_ !== newTab;
      this.saveCurrentTabScrollPosition_();
      this.clearSelectedTab_();
      if (id !== undefined) {
        this.setSelectedTabById_(id);
        this.restoreCurrentTabScrollPosition_();
      }

      if (changed)
        this.fire('selected-tab-change');
    },

    /**
     * This function updates the currently selected tab based on its internal
     * id. The corresponding light-dom element receives the selected attribute.
     */
    setSelectedTabById_: function(id) {
      this.selectedTab_ = this.tabs_[id];
      // Disconnect observer while we mutate the child.
      this.selectedTab_.observers.forAttributeSelected.disconnect();
      this.selectedTab_.content.setAttribute('selected', 'selected');
      // Reconnect the observer to watch for changes in the future.
      this.selectedTab_.observers.forAttributeSelected.observe(
          this.selectedTab_.content, { attributeFilter: ['selected'] });

    },

    saveTabStates: function() {
      // Scroll positions of unselected tabs have already been saved.
      this.saveCurrentTabScrollPosition_();
    },

    saveCurrentTabScrollPosition_: function() {
      if (this.selectedTab_) {
        this.selectedTab_.content._savedScrollTop =
            this.$['content-container'].scrollTop;
        this.selectedTab_.content._savedScrollLeft =
            this.$['content-container'].scrollLeft;
      }
    },

    restoreCurrentTabScrollPosition_: function() {
      if (this.selectedTab_) {
        this.$['content-container'].scrollTop =
            this.selectedTab_.content._savedScrollTop || 0;
        this.$['content-container'].scrollLeft =
            this.selectedTab_.content._savedScrollLeft || 0;
      }
    },

    /**
     * This function clears the currently selected tab. This handles removal
     * of the selected attribute from the light-dom element.
     */
    clearSelectedTab_: function() {
      if (this.selectedTab_) {
        // Disconnect observer while we mutate the child.
        this.selectedTab_.observers.forAttributeSelected.disconnect();
        this.selectedTab_.content.removeAttribute('selected');
        // Reconnect the observer to watch for changes in the future.
        this.selectedTab_.observers.forAttributeSelected.observe(
            this.selectedTab_.content, { attributeFilter: ['selected'] });
        this.selectedTab_ = undefined;
      }
    }
  });
  </script>
</polymer-element>
