<!--
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-diff-comment-thread.html">

<dom-module id="gr-diff-side">
  <template>
    <style>
      :host,
      .container {
        display: flex;
      }
      .lineNum:before,
      .code:before {
        /* To ensure the height is non-zero in these elements, a
           zero-width space is set as its content. The character
           itself doesn't matter. Just that there is something
           there. */
        content: '\200B';
      }
      .lineNum {
        background-color: #eee;
        color: #666;
        padding: 0 .75em;
        text-align: right;
      }
      .canComment .lineNum {
        cursor: pointer;
        text-decoration: underline;
      }
      .canComment .lineNum:hover {
        background-color: #ccc;
      }
      .code {
        white-space: pre;
      }
      .lightHighlight {
        background-color: var(--light-highlight-color);
      }
      hl,
      .darkHighlight {
        background-color: var(--dark-highlight-color);
      }
      .br:after {
        /* Line feed */
        content: '\A';
      }
      .tab {
        display: inline-block;
      }
      .tab.withIndicator:before {
        color: #C62828;
        /* >> character */
        content: '\00BB';
      }
      .numbers .filler {
        background-color: #eee;
      }
      .contextControl {
        background-color: #fef;
      }
      .contextControl a:link,
      .contextControl a:visited {
        display: block;
        text-decoration: none;
      }
      .numbers .contextControl {
        padding: 0 .75em;
        text-align: right;
      }
      .content .contextControl {
        text-align: center;
      }
    </style>
    <div class$="[[_computeContainerClass(canComment)]]">
      <div class="numbers" id="numbers"></div>
      <div class="content" id="content"></div>
    </div>
  </template>
  <script>
  (function() {
    'use strict';

    var CharCode = {
      LESS_THAN: '<'.charCodeAt(0),
      GREATER_THAN: '>'.charCodeAt(0),
      AMPERSAND: '&'.charCodeAt(0),
      SEMICOLON: ';'.charCodeAt(0),
    };

    var TAB_REGEX = /\t/g;

    Polymer({
      is: 'gr-diff-side',

      /**
       * Fired when an expand context control is clicked.
       *
       * @event expand-context
       */

      /**
       * Fired when a thread's height is changed.
       *
       * @event thread-height-change
       */

      /**
       * Fired when a draft should be added.
       *
       * @event add-draft
       */

      /**
       * Fired when a thread is removed.
       *
       * @event remove-thread
       */

      properties: {
        canComment: {
          type: Boolean,
          value: false,
        },
        content: {
          type: Array,
          notify: true,
          observer: '_contentChanged',
        },
        prefs: {
          type: Object,
          value: function() { return {}; },
        },
        changeNum: String,
        patchNum: String,
        path: String,
        projectConfig: {
          type: Object,
          observer: '_projectConfigChanged',
        },

        _lineFeedHTML: {
          type: String,
          value: '<span class="style-scope gr-diff-side br"></span>',
          readOnly: true,
        },
        _highlightStartTag: {
          type: String,
          value: '<hl class="style-scope gr-diff-side">',
          readOnly: true,
        },
        _highlightEndTag: {
          type: String,
          value: '</hl>',
          readOnly: true,
        },
      },

      listeners: {
        'tap': '_tapHandler',
      },

      observers: [ '_prefsChanged(prefs.*)' ],

      rowInserted: function(index) {
        this.renderLineIndexRange(index, index);
        this._updateDOMIndices();
      },

      rowRemoved: function(index) {
        var removedEls = Polymer.dom(this.root).querySelectorAll(
            '[data-index="' + index + '"]');
        for (var i = 0; i < removedEls.length; i++) {
          removedEls[i].parentNode.removeChild(removedEls[i]);
        }
        this._updateDOMIndices();
      },

      rowUpdated: function(index) {
        var removedEls = Polymer.dom(this.root).querySelectorAll(
            '[data-index="' + index + '"]');
        for (var i = 0; i < removedEls.length; i++) {
          removedEls[i].parentNode.removeChild(removedEls[i]);
        }
        this.renderLineIndexRange(index, index);
      },

      scrollToLine: function(lineNum) {
        if (isNaN(lineNum) || lineNum < 1) { return; }

        var el = this.$$('.numbers .lineNum[data-line-num="' + lineNum + '"]');
        if (!el) { return; }

        // Calculate where the line is relative to the window.
        var top = el.offsetTop;
        for (var offsetParent = el.offsetParent;
             offsetParent;
             offsetParent = offsetParent.offsetParent) {
          top += offsetParent.offsetTop;
        }

        // Scroll the element to the middle of the window. Dividing by a third
        // instead of half the inner height feels a bit better otherwise the
        // element appears to be below the center of the window even when it
        // isn't.
        window.scrollTo(0, top - (window.innerHeight / 3) - el.offsetHeight);
      },

      renderLineIndexRange: function(startIndex, endIndex) {
        this._render(this.content, startIndex, endIndex);
      },

      hideElementsWithIndex: function(index) {
        var els = Polymer.dom(this.root).querySelectorAll(
            '[data-index="' + index + '"]');
        for (var i = 0; i < els.length; i++) {
          els[i].setAttribute('hidden', true);
        }
      },

      getRowHeight: function(index) {
        var row = this.content[index];
        // Filler elements should not be taken into account when determining
        // height calculations.
        if (row.type == 'FILLER') {
          return 0;
        }
        if (row.height != null) {
          return row.height;
        }

        var selector = '[data-index="' + index + '"]'
        var els = Polymer.dom(this.root).querySelectorAll(selector);
        if (els.length != 2) {
          throw Error('Rows should only consist of two elements');
        }
        return Math.max(els[0].offsetHeight, els[1].offsetHeight);
      },

      getRowNaturalHeight: function(index) {
        var contentEl = this.$$('.content [data-index="' + index + '"]');
        return contentEl.naturalHeight || contentEl.offsetHeight;
      },

      setRowNaturalHeight: function(index) {
        var lineEl = this.$$('.numbers [data-index="' + index + '"]');
        var contentEl = this.$$('.content [data-index="' + index + '"]');
        contentEl.style.height = null;
        var height = contentEl.offsetHeight;
        lineEl.style.height = height + 'px';
        this.content[index].height = height;
        return height;
      },

      setRowHeight: function(index, height) {
        var selector = '[data-index="' + index + '"]';
        var els = Polymer.dom(this.root).querySelectorAll(selector);
        for (var i = 0; i < els.length; i++) {
          els[i].style.height = height + 'px';
        }
        this.content[index].height = height;
      },

      _updateDOMIndices: function() {
        // There is no way to select elements with a data-index greater than a
        // given value. For now, just update all DOM elements.
        var lineEls = Polymer.dom(this.root).querySelectorAll(
            '.numbers [data-index]');
        var contentEls = Polymer.dom(this.root).querySelectorAll(
            '.content [data-index]');
        if (lineEls.length != contentEls.length) {
          throw Error(
              'There must be the same number of line and content elements');
        }
        var index = 0;
        for (var i = 0; i < this.content.length; i++) {
          if (this.content[i].hidden) { continue; }

          lineEls[index].setAttribute('data-index', i);
          contentEls[index].setAttribute('data-index', i);
          index++;
        }
      },

      _prefsChanged: function(changeRecord) {
        var prefs = changeRecord.base;
        this.$.content.style.width = prefs.line_length + 'ch';
      },

      _projectConfigChanged: function(projectConfig) {
        var threadEls =
            Polymer.dom(this.root).querySelectorAll('gr-diff-comment-thread');
        for (var i = 0; i < threadEls.length; i++) {
          threadEls[i].projectConfig = projectConfig;
        }
      },

      _contentChanged: function(diff) {
        this._clearChildren(this.$.numbers);
        this._clearChildren(this.$.content);
        this._render(diff, 0, diff.length - 1);
      },

      _computeContainerClass: function(canComment) {
        return 'container' + (canComment ? ' canComment' : '');
      },

      _tapHandler: function(e) {
        var lineEl = Polymer.dom(e).rootTarget;
        if (!this.canComment || !lineEl.classList.contains('lineNum')) {
          return;
        }

        e.preventDefault();
        var index = parseInt(lineEl.getAttribute('data-index'), 10);
        var line = parseInt(lineEl.getAttribute('data-line-num'), 10);
        this.fire('add-draft', {
          index: index,
          line: line
        }, {bubbles: false});
      },

      _clearChildren: function(el) {
        while (el.firstChild) {
          el.removeChild(el.firstChild);
        }
      },

      _handleContextControlClick: function(context, e) {
        e.preventDefault();
        this.fire('expand-context', {context: context}, {bubbles: false});
      },

      _render: function(diff, startIndex, endIndex) {
        var beforeLineEl;
        var beforeContentEl;
        if (endIndex != diff.length - 1) {
          beforeLineEl = this.$$('.numbers [data-index="' + endIndex + '"]');
          beforeContentEl = this.$$('.content [data-index="' + endIndex + '"]');
          if (!beforeLineEl && !beforeContentEl) {
            // `endIndex` may be present within the model, but not in the DOM.
            // Insert it before its successive element.
            beforeLineEl = this.$$(
                '.numbers [data-index="' + (endIndex + 1) + '"]');
            beforeContentEl = this.$$(
                '.content [data-index="' + (endIndex + 1) + '"]');
          }
        }

        for (var i = startIndex; i <= endIndex; i++) {
          if (diff[i].hidden) { continue; }

          switch (diff[i].type) {
            case 'CODE':
              this._renderCode(diff[i], i, beforeLineEl, beforeContentEl);
              break;
            case 'FILLER':
              this._renderFiller(diff[i], i, beforeLineEl, beforeContentEl);
              break;
            case 'CONTEXT_CONTROL':
              this._renderContextControl(diff[i], i, beforeLineEl,
                  beforeContentEl);
              break;
            case 'COMMENT_THREAD':
              this._renderCommentThread(diff[i], i, beforeLineEl,
                  beforeContentEl);
              break;
          }
        }
      },

      _handleCommentThreadHeightChange: function(e) {
        var threadEl = Polymer.dom(e).rootTarget;
        var index = parseInt(threadEl.getAttribute('data-index'), 10);
        this.content[index].height = e.detail.height;
        var lineEl = this.$$('.numbers [data-index="' + index + '"]');
        lineEl.style.height = e.detail.height + 'px';
        this.fire('thread-height-change', {
          index: index,
          height: e.detail.height,
        }, {bubbles: false});
      },

      _handleCommentThreadDiscard: function(e) {
        var threadEl = Polymer.dom(e).rootTarget;
        var index = parseInt(threadEl.getAttribute('data-index'), 10);
        this.fire('remove-thread', {index: index}, {bubbles: false});
      },

      _renderCommentThread: function(thread, index, beforeLineEl,
          beforeContentEl) {
        var lineEl = this._createElement('div', 'commentThread');
        lineEl.classList.add('filler');
        lineEl.setAttribute('data-index', index);
        var threadEl = document.createElement('gr-diff-comment-thread');
        threadEl.addEventListener('height-change',
            this._handleCommentThreadHeightChange.bind(this));
        threadEl.addEventListener('discard',
            this._handleCommentThreadDiscard.bind(this));
        threadEl.setAttribute('data-index', index);
        threadEl.changeNum = this.changeNum;
        threadEl.patchNum = thread.patchNum || this.patchNum;
        threadEl.path = this.path;
        threadEl.comments = thread.comments;
        threadEl.showActions = this.canComment;
        threadEl.projectConfig = this.projectConfig;

        this.$.numbers.insertBefore(lineEl, beforeLineEl);
        this.$.content.insertBefore(threadEl, beforeContentEl);
      },

      _renderContextControl: function(control, index, beforeLineEl,
          beforeContentEl) {
        var lineEl = this._createElement('div', 'contextControl');
        lineEl.setAttribute('data-index', index);
        lineEl.textContent = '@@';
        var contentEl = this._createElement('div', 'contextControl');
        contentEl.setAttribute('data-index', index);
        var a = this._createElement('a');
        a.href = '#';
        a.textContent = 'Show ' + control.numLines + ' common ' +
            (control.numLines == 1 ? 'line' : 'lines') + '...';
        a.addEventListener('click',
            this._handleContextControlClick.bind(this, control));
        contentEl.appendChild(a);

        this.$.numbers.insertBefore(lineEl, beforeLineEl);
        this.$.content.insertBefore(contentEl, beforeContentEl);
      },

      _renderFiller: function(filler, index, beforeLineEl, beforeContentEl) {
        var lineFillerEl = this._createElement('div', 'filler');
        lineFillerEl.setAttribute('data-index', index);
        var fillerEl = this._createElement('div', 'filler');
        fillerEl.setAttribute('data-index', index);
        var numLines = filler.numLines || 1;

        lineFillerEl.textContent = '\n'.repeat(numLines);
        for (var i = 0; i < numLines; i++) {
          var newlineEl = this._createElement('span', 'br');
          fillerEl.appendChild(newlineEl);
        }

        this.$.numbers.insertBefore(lineFillerEl, beforeLineEl);
        this.$.content.insertBefore(fillerEl, beforeContentEl);
      },

      _renderCode: function(code, index, beforeLineEl, beforeContentEl) {
        var lineNumEl = this._createElement('div', 'lineNum');
        lineNumEl.setAttribute('data-line-num', code.lineNum);
        lineNumEl.setAttribute('data-index', index);
        var numLines = code.numLines || 1;
        lineNumEl.textContent = code.lineNum + '\n'.repeat(numLines);

        var contentEl = this._createElement('div', 'code');
        contentEl.setAttribute('data-line-num', code.lineNum);
        contentEl.setAttribute('data-index', index);

        if (code.highlight) {
          contentEl.classList.add(code.intraline.length > 0 ?
              'lightHighlight' : 'darkHighlight');
        }

        var html = util.escapeHTML(code.content);
        if (code.highlight && code.intraline.length > 0) {
          html = this._addIntralineHighlights(code.content, html,
              code.intraline);
        }
        if (numLines > 1) {
          html = this._addNewLines(code.content, html, numLines);
        }
        html = this._addTabWrappers(code.content, html);

        // If the html is equivalent to the text then it didn't get highlighted
        // or escaped. Use textContent which is faster than innerHTML.
        if (code.content == html) {
          contentEl.textContent = code.content;
        } else {
          contentEl.innerHTML = html;
        }

        this.$.numbers.insertBefore(lineNumEl, beforeLineEl);
        this.$.content.insertBefore(contentEl, beforeContentEl);
      },

      // Advance `index` by the appropriate number of characters that would
      // represent one source code character and return that index. For
      // example, for source code '<span>' the escaped html string is
      // '&lt;span&gt;'. Advancing from index 0 on the prior html string would
      // return 4, since &lt; maps to one source code character ('<').
      _advanceChar: function(html, index) {
        // Any tags don't count as characters
        while (index < html.length &&
               html.charCodeAt(index) == CharCode.LESS_THAN) {
          while (index < html.length &&
                 html.charCodeAt(index) != CharCode.GREATER_THAN) {
            index++;
          }
          index++;  // skip the ">" itself
        }
        // An HTML entity (e.g., &lt;) counts as one character.
        if (index < html.length &&
            html.charCodeAt(index) == CharCode.AMPERSAND) {
          while (index < html.length &&
                 html.charCodeAt(index) != CharCode.SEMICOLON) {
            index++;
          }
        }
        return index + 1;
      },

      _addIntralineHighlights: function(content, html, highlights) {
        var startTag = this._highlightStartTag;
        var endTag = this._highlightEndTag;

        for (var i = 0; i < highlights.length; i++) {
          var hl = highlights[i];

          var htmlStartIndex = 0;
          for (var j = 0; j < hl.startIndex; j++) {
            htmlStartIndex = this._advanceChar(html, htmlStartIndex);
          }

          var htmlEndIndex = 0;
          if (hl.endIndex != null) {
            for (var j = 0; j < hl.endIndex; j++) {
              htmlEndIndex = this._advanceChar(html, htmlEndIndex);
            }
          } else {
            // If endIndex isn't present, continue to the end of the line.
            htmlEndIndex = html.length;
          }
          // The start and end indices could be the same if a highlight is meant
          // to start at the end of a line and continue onto the next one.
          // Ignore it.
          if (htmlStartIndex != htmlEndIndex) {
            html = html.slice(0, htmlStartIndex) + startTag +
                  html.slice(htmlStartIndex, htmlEndIndex) + endTag +
                  html.slice(htmlEndIndex);
          }
        }
        return html;
      },

      _addNewLines: function(content, html, numLines) {
        var htmlIndex = 0;
        var indices = [];
        var numChars = 0;
        for (var i = 0; i < content.length; i++) {
          if (numChars > 0 && numChars % this.prefs.line_length == 0) {
            indices.push(htmlIndex);
          }
          htmlIndex = this._advanceChar(html, htmlIndex)
          if (content[i] == '\t') {
            numChars += this.prefs.tab_size;
          } else {
            numChars++;
          }
        }
        var result = html;
        var linesLeft = numLines;
        // Since the result string is being altered in place, start from the end
        // of the string so that the insertion indices are not affected as the
        // result string changes.
        for (var i = indices.length - 1; i >= 0; i--) {
          result = result.slice(0, indices[i]) + this._lineFeedHTML +
              result.slice(indices[i]);
          linesLeft--;
        }
        // numLines is the total number of lines this code block should take up.
        // Fill in the remaining ones.
        for (var i = 0; i < linesLeft; i++) {
          result += this._lineFeedHTML;
        }
        return result;
      },

      _addTabWrappers: function(content, html) {
        // TODO(andybons): CSS tab-size is not supported in IE.
        // Force this to be a number to prevent arbitrary injection.
        var tabSize = +this.prefs.tab_size;
        var htmlStr = '<span class="style-scope gr-diff-side tab ' +
            (this.prefs.show_tabs ? 'withIndicator" ' : '" ') +
            'style="tab-size:' + tabSize + ';' +
            '-moz-tab-size:' + tabSize + ';">\t</span>';
        return html.replace(TAB_REGEX, htmlStr);
      },

      _createElement: function(tagName, className) {
        var el = document.createElement(tagName);
        // When Shady DOM is being used, these classes are added to account for
        // Polymer's polyfill behavior. In order to guarantee sufficient
        // specificity within the CSS rules, these are added to every element.
        // Since the Polymer DOM utility functions (which would do this
        // automatically) are not being used for performance reasons, this is
        // done manually.
        el.classList.add('style-scope', 'gr-diff-side');
        if (!!className) {
          el.classList.add(className);
        }
        return el;
      },
    });
  })();
  </script>
</dom-module>
