// Copyright 2014 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
{namespace gitiles autoescape="strict"}

/**
 * Detail page showing blame info for a file.
 *
 * @param title human-readable revision name.
 * @param repositoryName name of this repository.
 * @param? menuEntries menu entries.
 * @param? customVariant variant name for custom styling.
 * @param breadcrumbs breadcrumbs for this page.
 * @param data blob data, matching the params for .blobBox.
 * @param? regions for non-binary files, list of regions, one per line, with the
 *     following keys:
 *       abbrevSha: abbreviated SHA-1 of revision for this line; if missing,
 *           assume blame info is missing.
 *       author: author information with at least "name" and "relativeTime"
 *           keys.
 *       time: time of the revision.
 *       blameUrl: URL for a blame of this file at this commit.
 *       commitUrl: URL for detail about the commit.
 *       diffUrl: URL for a diff of this file at this commit.
 *       class: class name for tr.
 *     All keys but "class" are optional.
 */
{template .blameDetail stricthtml="false"}
{if $regions}
  {call .header data="all"}
    {param css: [gitiles.PRETTIFY_CSS_URL] /}
    {param containerClass: 'Container--fullWidth' /}
  {/call}

  {call .blobHeader data="$data" /}

  <table class="Blame">
    {foreach $line in $data.lines}
      {let $i: index($line) /}
      {let $region: $regions[$i] /}
      <tr class="Blame-region {$region.class}">
        {if isNonnull($region.abbrevSha)}
          <td class="Blame-author">{$region.author.name}</td>
          <td class="Blame-sha1"><a class="u-sha1 u-monospace Blame-sha1" href="{$region.commitUrl}">{$region.abbrevSha}</a></td>
          <td class="Blame-time">{$region.author.time}</td>
          <td class="Blame-regionLink">
            [<a href="{$region.diffUrl}">{msg desc="text for diff URL"}diff{/msg}</a>]
            [<a href="{$region.blameUrl}">{msg desc="text for blame URL"}{$region.blameText}{/msg}</a>]
          </td>
        {else}
          <td colspan="4"></td>
        {/if}
        {let $n: $i + 1 /}
        <td class="Blame-lineNum">
          <a class="u-monospace u-lineNum" href="#{$n}" name="{$n}">{$n}</a>
        </td>
        <td class="u-pre u-monospace Blame-lineContent">
          {foreach $span in $line}
            <span class="{$span.classes}">{$span.text}</span>
          {/foreach}
        </td>
      </tr>
    {/foreach}
  </table>
{else}
  {call .header data="all" /}
  {call .blobDetail data="$data" /}
  <div class="FileContents-binary">
    {msg desc="blame not available for binary file"}
      No blame information available
    {/msg}
  </div>
{/if}

{call .footer}
  {param customVariant: $customVariant /}
{/call}
{/template}
