<!--
Copyright (C) 2015 The Android Open Source Project

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.
-->

<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="gr-account-link.html">
<link rel="import" href="gr-comment-list.html">
<link rel="import" href="gr-date-formatter.html">
<link rel="import" href="gr-linked-text.html">

<dom-module id="gr-message">
  <template>
    <style>
      :host {
        border-top: 1px solid #ddd;
        display: block;
        position: relative;
      }
      :host(:not([expanded])) {
        cursor: pointer;
      }
      gr-avatar {
        position: absolute;
        left: var(--default-horizontal-margin);
      }
      .collapsed .contentContainer {
        color: #777;
        white-space: nowrap;
        overflow-x: hidden;
        text-overflow: ellipsis;
      }
      .showAvatar.expanded .contentContainer {
        margin-left: calc(var(--default-horizontal-margin) + 2.5em);
        padding: 10px 0;
      }
      .showAvatar.collapsed .contentContainer {
        margin-left: calc(var(--default-horizontal-margin) + 1.75em);
        padding: 10px 75px 10px 0;
      }
      .hideAvatar.collapsed .contentContainer,
      .hideAvatar.expanded .contentContainer {
        margin-left: 0;
        padding: 10px 75px 10px 0;
      }
      .collapsed gr-avatar {
        top: 8px;
        height: 1.75em;
        width: 1.75em;
      }
      .expanded gr-avatar {
        top: 12px;
        height: 2.5em;
        width: 2.5em;
      }
      .name {
        font-weight: bold;
      }
      .collapsed .name,
      .collapsed .content,
      .collapsed .message {
        display: inline;
      }
      .collapsed gr-comment-list,
      .collapsed .replyContainer {
        display: none;
      }
      .collapsed .name {
        color: var(--default-text-color);
      }
      .expanded .name {
        cursor: pointer;
      }
      .date {
        color: #666;
        position: absolute;
        right: var(--default-horizontal-margin);
        top: 10px;
      }
      .replyContainer {
        padding: .5em 0 1em;
      }
      .reply {
        padding: .2em .6em .3em;
      }
    </style>
    <div class$="[[_computeClass(expanded, showAvatar)]]">
      <gr-avatar account="[[message.author]]" image-size="100"></gr-avatar>
      <div class="contentContainer">
        <div class="name" id="name">[[message.author.name]]</div>
        <div class="content">
          <gr-linked-text class="message"
              pre="[[expanded]]"
              content="[[message.message]]"
              disabled="[[!expanded]]"
              config="[[projectConfig.commentlinks]]"></gr-linked-text>
          <gr-comment-list
              comments="[[comments]]"
              change-num="[[changeNum]]"
              patch-num="[[message._revision_number]]"></gr-comment-list>
        </div>
        <a class="date" href$="[[_computeMessageHash(message)]]" on-tap="_handleLinkTap">
          <gr-date-formatter date-str="[[message.date]]"></gr-date-formatter>
        </a>
      </div>
      <div class="replyContainer" hidden$="[[!showReplyButton]]" hidden>
        <button class="reply" on-tap="_handleReplyTap">Reply</button>
      </div>
    </div>
  </template>
  <script>
  (function() {
    'use strict';

    Polymer({
      is: 'gr-message',

      /**
       * Fired when this message's permalink is tapped.
       *
       * @event scroll-to
       */

      /**
       * Fired when this message's reply link is tapped.
       *
       * @event reply
       */

      listeners: {
        'tap': '_tapHandler',
        'name.tap': '_collapseHandler',
      },

      properties: {
        changeNum: Number,
        message: Object,
        comments: {
          type: Object,
          observer: '_commentsChanged',
        },
        expanded: {
          type: Boolean,
          value: true,
          reflectToAttribute: true,
        },
        showAvatar: {
          type: Boolean,
          value: false,
        },
        showReplyButton: {
          type: Boolean,
          value: false,
        },
        projectConfig: Object,
      },

      ready: function() {
        app.configReady.then(function(cfg) {
          this.showAvatar = !!(cfg && cfg.plugin && cfg.plugin.has_avatars) &&
              this.message && this.message.author;
        }.bind(this));
      },

      _commentsChanged: function(value) {
        this.expanded = Object.keys(value || {}).length > 0;
      },

      _tapHandler: function(e) {
        if (this.expanded) { return; }
        this.expanded = true;
      },

      _collapseHandler: function(e) {
        if (!this.expanded) { return; }
        e.stopPropagation();
        this.expanded = false;
      },

      _computeClass: function(expanded, showAvatar) {
        var classes = [];
        classes.push(expanded ? 'expanded' : 'collapsed');
        classes.push(showAvatar ? 'showAvatar' : 'hideAvatar');
        return classes.join(' ');
      },

      _computeMessageHash: function(message) {
        return '#message-' + message.id;
      },

      _handleLinkTap: function(e) {
        e.preventDefault();

        this.fire('scroll-to', {message: this.message}, {bubbles: false});

        var hash = this._computeMessageHash(this.message);
        // Don't add the hash to the window history if it's already there.
        // Otherwise you mess up expected back button behavior.
        if (window.location.hash == hash) { return; }
        // Change the URL but don’t trigger a nav event. Otherwise it will
        // reload the page.
        page.show(window.location.pathname + hash, null, false);
      },

      _handleReplyTap: function(e) {
        e.preventDefault();
        this.fire('reply', {message: this.message});
      },
    });
  })();
  </script>
</dom-module>
