<!DOCTYPE html>

<html ng-app="Loader" ng-controller="Loader.Controller">

<head>
  <title ng-bind="windowTitle"></title>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.js"></script>
  <script src="constants.js"></script>
  <script src="loader.js"></script>
  <link rel="stylesheet" href="view.css">
</head>

<body>
  <h2>
    Instructions, roadmap, etc. are at
    <a href="http://tinyurl.com/SkiaRebaselineServer">
      http://tinyurl.com/SkiaRebaselineServer
    </a>
  </h2>

  <em ng-show="!extraColumnHeaders"><!-- show until data is loaded -->
    Loading results from <a href="{{resultsToLoad}}">{{resultsToLoad}}</a> ...
    {{loadingMessage}}
  </em>

  <div ng-show="extraColumnHeaders"><!-- everything: hide until data is loaded -->

    <div class="warning-div"
         ng-show="header[constants.KEY__HEADER__IS_EDITABLE] && header[constants.KEY__HEADER__IS_EXPORTED]">
      WARNING!  These results are editable and exported, so any user
      who can connect to this server over the network can modify them.
    </div>

    <div ng-show="header[constants.KEY__HEADER__TIME_UPDATED]">
      These results, from raw JSON file
      <a href="{{resultsToLoad}}">{{resultsToLoad}}</a>, current as of
      {{localTimeString(header[constants.KEY__HEADER__TIME_UPDATED])}}
      <br>
      To see other sets of results (all results, failures only, etc.),
      <a href="/">click here</a>
    </div>

    <div class="tab-wrapper"><!-- tabs -->
      <div class="tab-spacer" ng-repeat="tab in tabs">
        <div class="tab tab-{{tab == viewingTab}}"
             ng-click="setViewingTab(tab)">
          &nbsp;{{tab}} ({{numResultsPerTab[tab]}})&nbsp;
        </div>
        <div class="tab-spacer">
          &nbsp;
        </div>
      </div>
    </div><!-- tabs -->

    <div class="tab-main"><!-- main display area of selected tab -->

    <br>
    <!-- We only show the filters/settings table on the Unfiled tab. -->
    <table ng-show="viewingTab == defaultTab" border="1">
    <tr>
      <th colspan="4">
        Filters
      </th>
      <th>
        Settings
      </th>
    </tr>
    <tr valign="top">
      <td>
        resultType<br>
        <label ng-repeat="valueAndCount in extraColumnHeaders[constants.KEY__EXTRACOLUMNS__RESULT_TYPE][constants.KEY__EXTRACOLUMNHEADERS__VALUES_AND_COUNTS]">
          <input type="checkbox"
                 name="resultTypes"
                 value="{{valueAndCount[0]}}"
                 ng-checked="!isValueInSet(valueAndCount[0], hiddenResultTypes)"
                 ng-click="toggleValueInSet(valueAndCount[0], hiddenResultTypes); setUpdatesPending(true)">
          {{valueAndCount[0]}} ({{valueAndCount[1]}})<br>
        </label>
        <button ng-click="hiddenResultTypes = {}; updateResults()">
          all
        </button>
        <button ng-click="hiddenResultTypes = {}; toggleValuesInSet(allResultTypes, hiddenResultTypes); updateResults()">
          none
        </button>
        <button ng-click="toggleValuesInSet(allResultTypes, hiddenResultTypes); updateResults()">
          toggle
        </button>
      </td>
      <td ng-repeat="category in [constants.KEY__EXTRACOLUMNS__BUILDER, constants.KEY__EXTRACOLUMNS__TEST]">
        {{category}}
        <br>
        <input type="text"
               ng-model="categoryValueMatch[category]"
               ng-change="setUpdatesPending(true)"/>
        <br>
        <button ng-click="setCategoryValueMatch(category, '')"
                ng-disabled="('' == categoryValueMatch[category])">
          clear (show all)
        </button>
      </td>
      <td>
        config<br>
        <label ng-repeat="valueAndCount in extraColumnHeaders[constants.KEY__EXTRACOLUMNS__CONFIG][constants.KEY__EXTRACOLUMNHEADERS__VALUES_AND_COUNTS]">
          <input type="checkbox"
                 name="configs"
                 value="{{valueAndCount[0]}}"
                 ng-checked="!isValueInSet(valueAndCount[0], hiddenConfigs)"
                 ng-click="toggleValueInSet(valueAndCount[0], hiddenConfigs); setUpdatesPending(true)">
          {{valueAndCount[0]}} ({{valueAndCount[1]}})<br>
        </label>
        <button ng-click="hiddenConfigs = {}; updateResults()">
          all
        </button>
        <button ng-click="hiddenConfigs = {}; toggleValuesInSet(allConfigs, hiddenConfigs); updateResults()">
          none
        </button>
        <button ng-click="toggleValuesInSet(allConfigs, hiddenConfigs); updateResults()">
          toggle
        </button>
      </td>
      <td><table>
        <tr><td>
          <input type="checkbox" ng-model="showThumbnailsPending"
                 ng-init="showThumbnailsPending = true"
                 ng-change="areUpdatesPending = true"/>
          Show thumbnails
        </td></tr>
        <tr><td>
          <input type="checkbox" ng-model="mergeIdenticalRowsPending"
                 ng-init="mergeIdenticalRowsPending = true"
                 ng-change="areUpdatesPending = true"/>
          Merge identical rows
        </td></tr>
        <tr><td>
          Image width
          <input type="text" ng-model="imageSizePending"
                 ng-init="imageSizePending=100"
                 ng-change="areUpdatesPending = true"
                 maxlength="4"/>
        </td></tr>
        <tr><td>
          Max records to display
          <input type="text" ng-model="displayLimitPending"
                 ng-init="displayLimitPending=50"
                 ng-change="areUpdatesPending = true"
                 maxlength="4"/>
        </td></tr>
        <tr><td>
          <button class="update-results-button"
                  ng-click="updateResults()"
                  ng-disabled="!areUpdatesPending">
            Update Results
          </button>
        </td></tr>
      </tr></table></td>
    </tr>
  </table>

      <p>

      <!-- Submission UI that we only show in the Pending Approval tab. -->
      <div ng-show="'Pending Approval' == viewingTab">
        <div style="display:inline-block">
          <button style="font-size:20px"
                  ng-click="submitApprovals(filteredImagePairs)"
                  ng-disabled="submitPending || (filteredImagePairs.length == 0)">
            Update these {{filteredImagePairs.length}} expectations on the server
          </button>
        </div>
        <div style="display:inline-block">
          <div style="font-size:20px"
               ng-show="submitPending">
            Submitting, please wait...
          </div>
        </div>
        <div>
          Advanced settings...
          <input type="checkbox" ng-model="showSubmitAdvancedSettings">
          show
          <ul ng-show="showSubmitAdvancedSettings">
            <li ng-repeat="setting in [constants.KEY__EXPECTATIONS__REVIEWED, constants.KEY__EXPECTATIONS__IGNOREFAILURE]">
              {{setting}}
              <input type="checkbox" ng-model="submitAdvancedSettings[setting]">
            </li>
            <li ng-repeat="setting in ['bug']">
              {{setting}}
              <input type="text" ng-model="submitAdvancedSettings[setting]">
            </li>
          </ul>
        </div>
      </div>

      <p>

    <table border="0"><tr><td> <!-- table holding results header + results table -->
      <table border="0" width="100%"> <!-- results header -->
        <tr>
          <td>
            Found {{filteredImagePairs.length}} matches;
            <span ng-show="filteredImagePairs.length > limitedImagePairs.length">
              displaying the first {{limitedImagePairs.length}}.
            </span>
            <span ng-show="filteredImagePairs.length <= limitedImagePairs.length">
              displaying them all.
            </span>
            <span ng-show="renderEndTime > renderStartTime">
              Rendered in {{(renderEndTime - renderStartTime).toFixed(0)}} ms.
            </span>
            <br>
            (click on the column header radio buttons to re-sort by that column)
          </td>
          <td align="right">
            <div>
              all tests shown:
              <button ng-click="selectAllImagePairs()">
                select
              </button>
              <button ng-click="clearAllImagePairs()">
                clear
              </button>
              <button ng-click="toggleAllImagePairs()">
                toggle
              </button>
            </div>
            <div ng-repeat="otherTab in tabs">
              <button ng-click="moveSelectedImagePairsToTab(otherTab)"
                      ng-disabled="selectedImagePairs.length == 0"
                      ng-show="otherTab != viewingTab">
                move {{selectedImagePairs.length}} selected tests to {{otherTab}} tab
              </button>
            </div>
          </td>
        </tr>
      </table> <!-- results header -->
      </td></tr><tr><td>
      <table border="1" ng-app="diff_viewer"> <!-- results -->
        <tr>
          <!-- Most column headers are displayed in a common fashion... -->
          <th ng-repeat="categoryName in [constants.KEY__EXTRACOLUMNS__RESULT_TYPE, constants.KEY__EXTRACOLUMNS__BUILDER, constants.KEY__EXTRACOLUMNS__TEST, constants.KEY__EXTRACOLUMNS__CONFIG]">
            <input type="radio"
                   name="sortColumnRadio"
                   value="{{categoryName}}"
                   ng-checked="(sortColumnKey == categoryName)"
                   ng-click="sortResultsBy(constants.KEY__IMAGEPAIRS__EXTRACOLUMNS, categoryName)">
            {{categoryName}}
          </th>
          <!-- ... but there are a few columns where we display things differently. -->
          <th>
            <input type="radio"
                   name="sortColumnRadio"
                   value="bugs"
                   ng-checked="(sortColumnKey == constants.KEY__EXPECTATIONS__BUGS)"
                   ng-click="sortResultsBy(constants.KEY__IMAGEPAIRS__EXPECTATIONS, constants.KEY__EXPECTATIONS__BUGS)">
            bugs
          </th>
          <th width="{{imageSize}}">
            <input type="radio"
                   name="sortColumnRadio"
                   value="imageA"
                   ng-checked="(sortColumnKey == constants.KEY__IMAGEPAIRS__IMAGE_A_URL)"
                   ng-click="sortResultsBy('none', constants.KEY__IMAGEPAIRS__IMAGE_A_URL)">
            {{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_A][constants.KEY__IMAGESETS__FIELD__DESCRIPTION]}}
          </th>
          <th width="{{imageSize}}">
            <input type="radio"
                   name="sortColumnRadio"
                   value="imageB"
                   ng-checked="(sortColumnKey == constants.KEY__IMAGEPAIRS__IMAGE_B_URL)"
                   ng-click="sortResultsBy('none', constants.KEY__IMAGEPAIRS__IMAGE_B_URL)">
            {{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_B][constants.KEY__IMAGESETS__FIELD__DESCRIPTION]}}
          </th>
          <th width="{{imageSize}}">
            <input type="radio"
                   name="sortColumnRadio"
                   value="percentDifferingPixels"
                   ng-checked="(sortColumnKey == constants.KEY__DIFFERENCES__PERCENT_DIFF_PIXELS)"
                   ng-click="sortResultsBy(constants.KEY__IMAGEPAIRS__DIFFERENCES, constants.KEY__DIFFERENCES__PERCENT_DIFF_PIXELS)">
            differing pixels in white
          </th>
          <th width="{{imageSize}}">
            <input type="radio"
                   name="sortColumnRadio"
                   value="perceptualDiff"
                   ng-checked="(sortColumnKey == constants.KEY__DIFFERENCES__PERCEPTUAL_DIFF)"
                   ng-click="sortResultsBy(constants.KEY__IMAGEPAIRS__DIFFERENCES, constants.KEY__DIFFERENCES__PERCEPTUAL_DIFF)">
            perceptual difference
            <br>
            <input type="range" ng-model="pixelDiffBgColorBrightness"
                   ng-init="pixelDiffBgColorBrightness=64; pixelDiffBgColor=brightnessStringToHexColor(pixelDiffBgColorBrightness)"
                   ng-change="pixelDiffBgColor=brightnessStringToHexColor(pixelDiffBgColorBrightness)"
                   title="image background brightness"
                   min="0" max="255"/>
          </th>
          <th>
            <!-- imagepair-selection checkbox column -->
          </th>
        </tr>

        <tr ng-repeat="imagePair in limitedImagePairs" valign="top"
            ng-class-odd="'results-odd'" ng-class-even="'results-even'"
            results-updated-callback-directive>
          <td>
            {{imagePair[constants.KEY__IMAGEPAIRS__EXTRACOLUMNS][constants.KEY__EXTRACOLUMNS__RESULT_TYPE]}}
            <br>
            <button class="show-only-button"
                    ng-show="viewingTab == defaultTab"
                    ng-click="showOnlyResultType(imagePair[constants.KEY__IMAGEPAIRS__EXTRACOLUMNS][constants.KEY__EXTRACOLUMNS__RESULT_TYPE])"
                    title="show only results of type {{imagePair[constants.KEY__IMAGEPAIRS__EXTRACOLUMNS][constants.KEY__EXTRACOLUMNS__RESULT_TYPE]}}">
              show only
            </button>
            <br>
            <button class="show-all-button"
                    ng-show="viewingTab == defaultTab"
                    ng-disabled="0 == setSize(hiddenResultTypes)"
                    ng-click="showAllResultTypes()"
                    title="show results of all types">
              show all
            </button>
          </td>
          <td ng-repeat="categoryName in [constants.KEY__EXTRACOLUMNS__BUILDER, constants.KEY__EXTRACOLUMNS__TEST]">
            {{imagePair[constants.KEY__IMAGEPAIRS__EXTRACOLUMNS][categoryName]}}
            <br>
            <button class="show-only-button"
                    ng-show="viewingTab == defaultTab"
                    ng-disabled="imagePair[constants.KEY__IMAGEPAIRS__EXTRACOLUMNS][categoryName] == categoryValueMatch[categoryName]"
                    ng-click="setCategoryValueMatch(categoryName, imagePair[constants.KEY__IMAGEPAIRS__EXTRACOLUMNS][categoryName])"
                    title="show only results of {{categoryName}} {{imagePair[constants.KEY__IMAGEPAIRS__EXTRACOLUMNS][categoryName]}}">
              show only
            </button>
            <br>
            <button class="show-all-button"
                    ng-show="viewingTab == defaultTab"
                    ng-disabled="'' == categoryValueMatch[categoryName]"
                    ng-click="setCategoryValueMatch(categoryName, '')"
                    title="show results of all {{categoryName}}s">
              show all
            </button>
          </td>
          <td>
            {{imagePair[constants.KEY__IMAGEPAIRS__EXTRACOLUMNS][constants.KEY__EXTRACOLUMNS__CONFIG]}}
            <br>
            <button class="show-only-button"
                    ng-show="viewingTab == defaultTab"
                    ng-click="showOnlyConfig(imagePair[constants.KEY__IMAGEPAIRS__EXTRACOLUMNS][constants.KEY__EXTRACOLUMNS__CONFIG])"
                    title="show only results of config {{imagePair[constants.KEY__IMAGEPAIRS__EXTRACOLUMNS][constants.KEY__EXTRACOLUMNS__CONFIG]}}">
              show only
            </button>
            <br>
            <button class="show-all-button"
                    ng-show="viewingTab == defaultTab"
                    ng-disabled="0 == setSize(hiddenConfigs)"
                    ng-click="showAllConfigs()"
                    title="show results of all configs">
              show all
            </button>
          </td>
          <td>
            <a ng-repeat="bug in imagePair[constants.KEY__IMAGEPAIRS__EXPECTATIONS][constants.KEY__EXPECTATIONS__BUGS]"
               href="https://code.google.com/p/skia/issues/detail?id={{bug}}"
               target="_blank">
              {{bug}}
            </a>
          </td>

          <!-- image A -->
          <td width="{{imageSize}}" ng-if="imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN] > 0" rowspan="{{imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN]}}">
            <div ng-if="imagePair[constants.KEY__IMAGEPAIRS__IMAGE_A_URL] != null">
              <a href="{{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_A][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{imagePair[constants.KEY__IMAGEPAIRS__IMAGE_A_URL]}}" target="_blank">View Image</a><br/>
              <img ng-if="showThumbnails"
                   width="{{imageSize}}"
                   ng-src="{{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_A][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{imagePair[constants.KEY__IMAGEPAIRS__IMAGE_A_URL]}}" />
            </div>
            <div ng-show="imagePair[constants.KEY__IMAGEPAIRS__IMAGE_A_URL] == null"
                 style="text-align:center">
              &ndash;none&ndash;
            </div>
          </td>

          <!-- image B -->
          <td width="{{imageSize}}" ng-if="imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN] > 0" rowspan="{{imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN]}}">
            <div ng-if="imagePair[constants.KEY__IMAGEPAIRS__IMAGE_B_URL] != null">
              <a href="{{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_B][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{imagePair[constants.KEY__IMAGEPAIRS__IMAGE_B_URL]}}" target="_blank">View Image</a><br/>
              <img ng-if="showThumbnails"
                   width="{{imageSize}}"
                   ng-src="{{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_B][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{imagePair[constants.KEY__IMAGEPAIRS__IMAGE_B_URL]}}" />
            </div>
            <div ng-show="imagePair[constants.KEY__IMAGEPAIRS__IMAGE_B_URL] == null"
                 style="text-align:center">
              &ndash;none&ndash;
            </div>
          </td>

          <!-- whitediffs: every differing pixel shown in white -->
          <td width="{{imageSize}}" ng-if="imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN] > 0" rowspan="{{imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN]}}">
            <div ng-if="imagePair[constants.KEY__IMAGEPAIRS__IS_DIFFERENT]"
                 title="{{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__NUM_DIFF_PIXELS] | number:0}} of {{(100 * imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__NUM_DIFF_PIXELS] / imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__PERCENT_DIFF_PIXELS]) | number:0}} pixels ({{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__PERCENT_DIFF_PIXELS].toFixed(4)}}%) differ from expectation.">

              <a href="{{imageSets[constants.KEY__IMAGESETS__SET__WHITEDIFFS][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{getImageDiffRelativeUrl(imagePair)}}" target="_blank">View Image</a><br/>
              <img ng-if="showThumbnails"
                   width="{{imageSize}}"
                   ng-src="{{imageSets[constants.KEY__IMAGESETS__SET__WHITEDIFFS][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{getImageDiffRelativeUrl(imagePair)}}" />
              <br/>
              {{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__PERCENT_DIFF_PIXELS].toFixed(4)}}%
              ({{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__NUM_DIFF_PIXELS]}})
            </div>
            <div ng-show="!imagePair[constants.KEY__IMAGEPAIRS__IS_DIFFERENT]"
                 style="text-align:center">
              &ndash;none&ndash;
            </div>
          </td>

          <!-- diffs: per-channel RGB deltas -->
          <td width="{{imageSize}}" ng-if="imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN] > 0" rowspan="{{imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN]}}">
            <div ng-if="imagePair[constants.KEY__IMAGEPAIRS__IS_DIFFERENT]"
                 title="Perceptual difference measure is {{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__PERCEPTUAL_DIFF].toFixed(4)}}%.  Maximum difference per channel: R={{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__MAX_DIFF_PER_CHANNEL][0]}}, G={{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__MAX_DIFF_PER_CHANNEL][1]}}, B={{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__MAX_DIFF_PER_CHANNEL][2]}}">

              <a href="{{imageSets[constants.KEY__IMAGESETS__SET__DIFFS][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{getImageDiffRelativeUrl(imagePair)}}" target="_blank">View Image</a><br/>
              <img ng-if="showThumbnails"
                   ng-style="{backgroundColor: pixelDiffBgColor}"
                   width="{{imageSize}}"
                   ng-src="{{imageSets[constants.KEY__IMAGESETS__SET__DIFFS][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{getImageDiffRelativeUrl(imagePair)}}" />
              <br/>
              {{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__PERCEPTUAL_DIFF].toFixed(4)}}%
              {{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__MAX_DIFF_PER_CHANNEL]}}
            </div>
            <div ng-show="!imagePair[constants.KEY__IMAGEPAIRS__IS_DIFFERENT]"
                 style="text-align:center">
              &ndash;none&ndash;
            </div>
          </td>

          <td ng-if="imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN] > 0" rowspan="{{imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN]}}">
            <br/>
            <input type="checkbox"
                   name="rowSelect"
                   value="{{imagePair.index}}"
                   ng-checked="isValueInArray(imagePair.index, selectedImagePairs)"
                   ng-click="toggleSomeImagePairs($index, imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN])">
        </tr>
      </table> <!-- imagePairs -->
    </td></tr></table> <!-- table holding results header + imagePairs table -->

  </div><!-- main display area of selected tab -->
  </div><!-- everything: hide until data is loaded -->

</body>
</html>