  <!-- The <list-page-sk> custom element declaration.

  Displays the summary of tests that match the search query in the URL.

  Attributes:
    None

  Methods:
    pageSelected(ctx) - Called by the router when the view becomes visible.
          ctx is the context provided in the route dispatch of page.js.

    pageDeselected - Called by the router when the view is no longer visible.

  Events:
    None

  Mailboxes:
    None

  -->
<link rel="import" href="bower_components/polymer/polymer.html">
<link rel="import" href="bower_components/iron-flex-layout/iron-flex-layout-classes.html">
<link rel="import" href="bower_components/paper-toggle-button/paper-toggle-button.html">
<link rel="import" href="bower_components/iron-icons/iron-icons.html">
<link rel="import" href="bower_components/paper-button/paper-button.html">
<link rel="import" href="bower_components/paper-menu-button/paper-menu-button.html">

<link rel="import" href="../common/imp/sort.html">

<link rel="import" href="activity-sk.html">
<link rel="import" href="test-summary-sk.html">
<link rel="import" href="search-controls-sk.html">
<link rel="import" href="shared-styles.html">

<dom-module id="list-page-sk">
  <template>
    <style include="iron-flex iron-flex-alignment"></style>
    <style include="shared-styles"></style>
    <style>
      test-summary-sk {
        display: block;
        margin-top: 0.5em;
      }

      .header {
        width: 25em;
        float: left;
        margin-left: .6em;
        color: #1F78B4;
        text-decoration: none;
        cursor: pointer;
        text-transform: uppercase;
      }

      .header.short {
        width: 6em;
      }

      #core {
        margin-top: 1em;
        margin-left: 1em;
      }

      paper-button[disabled] {
        background: transparent;
        color: #1F78B4;
      }

      .wrapper {
        margin-top: 1em;
      }

      .actionMenu {
        max-width: 10em;
        margin-left: 10em;
      }

      .actionButton {
        color: green;
      };

    </style>

    <div id="core" class="vertical layout">
      <activity-sk id="activityBar" busy="{{_hideAll}}"></activity-sk>
      <div hidden$="{{_hideAll}}">
        <div class="layout horizontal">
          <search-controls-sk id="searchControls"></search-controls-sk>
          <paper-menu-button close-on-activate no-animations class="actionMenu">
            <paper-button class="dropdown-trigger actionButton" raised>Actions</paper-button>
            <paper-menu class="dropdown-content">
              <paper-item on-tap="_handleSwitchToSearch">See All Digests</paper-item>
            </paper-menu>
          </paper-menu-button>
        </div>

        <div class="wrapper">
          <sort-sk target="summaries">
            <div class="horizontal layout">
              <a class="header" data-key="name" data-alpha=true>Name</a>
              <a class="header short">Grid</a>
              <a class="header short">Cluster</a>
              <a class="header short" data-key="pos">Pos</a>
              <a class="header short" data-key="neg">Neg</a>
              <a class="header short" data-key="untriaged">Unt</a>
              <a class="header short" data-key="num">Total</a>
              <a class="header">Blame</a>
            </div>
          </sort-sk>
          <div id="summaries"></div>
        </div>
      </div>
    </div>
  </template>

  <script>
   (function() {

    var NAME_FIELD = "name";

    Polymer({
      is: "list-page-sk",

      properties: {
        _state: {
          type: Object,
          value: null,
          notify: true
        }
      },

      behaviors: [gold.PageStateBehavior],

      ready: function() {
        this.listen(this.$.searchControls, 'state-change', '_handleStateChange');
        this._setDefaultState(gold.defaultSearchState, false);
      },

      pageSelected: function(ctx) {
        this._loadParamset();
        this._initState(ctx, this._getDefaultStateWithCorpus());
        this.$.searchControls.setState(this._state);
        this._load();
      },

      pageDeselected: function() {},

      _handleStateChange: function(ev) {
        // Reload the page with the new  state in the query parameters.
        this._redirectToState(ev.detail);
      },

      _load: function() {
        var q = window.location.search;
        this.$.activityBar.startSpinner("Loading ...");
        sk.get("/json/list" + q).then(JSON.parse).then(function (json) {
          // Remove the name field from the current query.
          this._currentQuery = sk.query.toParamSet(this._state.query);
          delete this._currentQuery[NAME_FIELD];

          this._displaySummaries(json);
          this.$.activityBar.stopSpinner();
        }.bind(this)).catch(function(e) {
          this.$.activityBar.stopSpinner();
          sk.errorMessage(e);
        }.bind(this));
      },

      _displaySummaries: function(summaries) {
        var container = this.$.summaries;
        sk.clearChildren(container);
        var stateCopy = gold.filterEmpty(this._state);

        // The search string for the cluster link includes
        // positive, negatives and untriaged.
        var clusterStateCopy = gold.filterEmpty(this._state);
        clusterStateCopy.pos = true;
        clusterStateCopy.neg = true;
        clusterStateCopy.unt = true;

        summaries.forEach(function(c, i) {
          var s = document.createElement("test-summary-sk");
          s.summary = c;
          s.search = this._searchStr(stateCopy, c);
          s.clusterSearch = this._searchStr(clusterStateCopy, c);
          container.appendChild(s);
        }.bind(this));
      },

      _searchStr: function(baseState, summary) {
        // Swap out the test name and generate the search string.
        this._currentQuery[NAME_FIELD] = [summary.name];
        baseState.query = sk.query.fromParamSet(this._currentQuery);
        return sk.query.fromObject(baseState);
      },

      _loadParamset: function() {
        sk.get("/json/paramset").then(JSON.parse).then(function (json) {
          this.$.searchControls.setParamSet(json);
        }.bind(this)).catch(sk.errorMessage);
      },

      _handleSwitchToSearch: function() {
        this._redirectToState({}, "/search");
      }
    });

    })();
  </script>
</dom-module>
