/**
 * @license
 * Copyright (C) 2016 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.
 */
(function() {
  'use strict';

  const PATCH_SET_PREFIX_PATTERN = /^Patch Set \d+: /;
  const LABEL_TITLE_SCORE_PATTERN = /^([A-Za-z0-9-]+)([+-]\d+)$/;

  Polymer({
    is: 'gr-message',
    _legacyUndefinedCheck: true,

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

    /**
     * Fired when the message's timestamp is tapped.
     *
     * @event message-anchor-tap
     */

    listeners: {
      tap: '_handleTap',
    },

    properties: {
      changeNum: Number,
      /** @type {?} */
      message: Object,
      author: {
        type: Object,
        computed: '_computeAuthor(message)',
      },
      comments: {
        type: Object,
        observer: '_commentsChanged',
      },
      config: Object,
      hideAutomated: {
        type: Boolean,
        value: false,
      },
      hidden: {
        type: Boolean,
        computed: '_computeIsHidden(hideAutomated, isAutomated)',
        reflectToAttribute: true,
      },
      isAutomated: {
        type: Boolean,
        computed: '_computeIsAutomated(message)',
      },
      showAvatar: {
        type: Boolean,
        computed: '_computeShowAvatar(author, config)',
      },
      showOnBehalfOf: {
        type: Boolean,
        computed: '_computeShowOnBehalfOf(message)',
      },
      showReplyButton: {
        type: Boolean,
        computed: '_computeShowReplyButton(message, _loggedIn)',
      },
      projectName: {
        type: String,
        observer: '_projectNameChanged',
      },

      /**
       * A mapping from label names to objects representing the minimum and
       * maximum possible values for that label.
       */
      labelExtremes: Object,

      /**
       * @type {{ commentlinks: Array }}
       */
      _projectConfig: Object,
      // Computed property needed to trigger Polymer value observing.
      _expanded: {
        type: Object,
        computed: '_computeExpanded(message.expanded)',
      },
      _loggedIn: {
        type: Boolean,
        value: false,
      },
    },

    behaviors: [
      Gerrit.FireBehavior,
    ],

    observers: [
      '_updateExpandedClass(message.expanded)',
    ],

    ready() {
      this.$.restAPI.getConfig().then(config => {
        this.config = config;
      });
      this.$.restAPI.getLoggedIn().then(loggedIn => {
        this._loggedIn = loggedIn;
      });
    },

    _updateExpandedClass(expanded) {
      if (expanded) {
        this.classList.add('expanded');
      } else {
        this.classList.remove('expanded');
      }
    },

    _computeAuthor(message) {
      return message.author || message.updated_by;
    },

    _computeShowAvatar(author, config) {
      return !!(author && config && config.plugin && config.plugin.has_avatars);
    },

    _computeShowOnBehalfOf(message) {
      const author = message.author || message.updated_by;
      return !!(author && message.real_author &&
          author._account_id != message.real_author._account_id);
    },

    _computeShowReplyButton(message, loggedIn) {
      return message && !!message.message && loggedIn &&
          !this._computeIsAutomated(message);
    },

    _computeExpanded(expanded) {
      return expanded;
    },

    /**
     * If there is no value set on the message object as to whether _expanded
     * should be true or not, then _expanded is set to true if there are
     * inline comments (otherwise false).
     */
    _commentsChanged(value) {
      if (this.message && this.message.expanded === undefined) {
        this.set('message.expanded', Object.keys(value || {}).length > 0);
      }
    },

    _handleTap(e) {
      if (this.message.expanded) { return; }
      e.stopPropagation();
      this.set('message.expanded', true);
    },

    _handleAuthorTap(e) {
      if (!this.message.expanded) { return; }
      e.stopPropagation();
      this.set('message.expanded', false);
    },

    _computeIsAutomated(message) {
      return !!(message.reviewer ||
          this._computeIsReviewerUpdate(message) ||
          (message.tag && message.tag.startsWith('autogenerated')));
    },

    _computeIsHidden(hideAutomated, isAutomated) {
      return hideAutomated && isAutomated;
    },

    _computeIsReviewerUpdate(event) {
      return event.type === 'REVIEWER_UPDATE';
    },

    _getScores(message) {
      if (!message.message) { return []; }
      const line = message.message.split('\n', 1)[0];
      const patchSetPrefix = PATCH_SET_PREFIX_PATTERN;
      if (!line.match(patchSetPrefix)) { return []; }
      const scoresRaw = line.split(patchSetPrefix)[1];
      if (!scoresRaw) { return []; }
      return scoresRaw.split(' ')
          .map(s => s.match(LABEL_TITLE_SCORE_PATTERN))
          .filter(ms => ms && ms.length === 3)
          .map(ms => ({label: ms[1], value: ms[2]}));
    },

    _computeScoreClass(score, labelExtremes) {
      // Polymer 2: check for undefined
      if ([score, labelExtremes].some(arg => arg === undefined)) {
        return '';
      }
      const classes = [];
      if (score.value > 0) {
        classes.push('positive');
      } else if (score.value < 0) {
        classes.push('negative');
      }
      const extremes = labelExtremes[score.label];
      if (extremes) {
        const extremes = labelExtremes[score.label];
        const intScore = parseInt(score.value, 10);
        if (intScore === extremes.max) {
          classes.push('max');
        } else if (intScore === extremes.min) {
          classes.push('min');
        }
      }
      return classes.join(' ');
    },

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

    _handleAnchorTap(e) {
      e.preventDefault();
      this.dispatchEvent(new CustomEvent('message-anchor-tap', {
        bubbles: true,
        composed: true,
        detail: {id: this.message.id},
      }));
    },

    _handleReplyTap(e) {
      e.preventDefault();
      this.fire('reply', {message: this.message});
    },

    _projectNameChanged(name) {
      this.$.restAPI.getProjectConfig(name).then(config => {
        this._projectConfig = config;
      });
    },

    _computeExpandToggleIcon(expanded) {
      return expanded ? 'gr-icons:expand-less' : 'gr-icons:expand-more';
    },

    _toggleExpanded(e) {
      e.stopPropagation();
      this.set('message.expanded', !this.message.expanded);
    },
  });
})();

@@ -5877,61 +5877,8 @@
 ) %7B%0A
-        const extremes = labelExtremes%5Bscore.label%5D;%0A
     

Remove duplicate const from gr-message