<!--
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.
-->
<link rel="import" href="../../../bower_components/polymer/polymer.html">
<link rel="import" href="../../core/gr-reporting/gr-reporting.html">
<link rel="import" href="../gr-diff-comment-thread/gr-diff-comment-thread.html">
<link rel="import" href="../gr-diff-comment-thread-group/gr-diff-comment-thread-group.html">
<link rel="import" href="../gr-diff-processor/gr-diff-processor.html">
<link rel="import" href="../gr-ranged-comment-layer/gr-ranged-comment-layer.html">
<link rel="import" href="../gr-syntax-layer/gr-syntax-layer.html">

<dom-module id="gr-diff-builder">
  <template>
    <div class="contentWrapper">
      <content></content>
    </div>
    <gr-ranged-comment-layer
        id="rangeLayer"
        comments="[[comments]]"></gr-ranged-comment-layer>
    <gr-syntax-layer
        id="syntaxLayer"
        diff="[[diff]]"></gr-syntax-layer>
    <gr-diff-processor
        id="processor"
        groups="{{_groups}}"></gr-diff-processor>
    <gr-reporting id="reporting"></gr-reporting>
  </template>
  <script src="../gr-diff/gr-diff-line.js"></script>
  <script src="../gr-diff/gr-diff-group.js"></script>
  <script src="../gr-diff-highlight/gr-annotation.js"></script>
  <script src="gr-diff-builder.js"></script>
  <script src="gr-diff-builder-side-by-side.js"></script>
  <script src="gr-diff-builder-unified.js"></script>
  <script src="gr-diff-builder-image.js"></script>
  <script>
    (function() {
      'use strict';

      var DiffViewMode = {
        SIDE_BY_SIDE: 'SIDE_BY_SIDE',
        UNIFIED: 'UNIFIED_DIFF',
      };

      var TimingLabel = {
        TOTAL: 'Diff Total Render',
        CONTENT: 'Diff Content Render',
        SYNTAX: 'Diff Syntax Render',
      };

      // If any line of the diff is more than the character limit, then disable
      // syntax highlighting for the entire file.
      var SYNTAX_MAX_LINE_LENGTH = 500;

      var TRAILING_WHITESPACE_PATTERN = /\s+$/;

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

        /**
         * Fired when the diff begins rendering.
         *
         * @event render-start
         */

        /**
         * Fired when the diff is rendered.
         *
         * @event render
         */

        /**
         * Fired when the diff finishes rendering text content, but not
         * necessarily syntax highlights.
         *
         * @event render-content
         */

        properties: {
          diff: Object,
          viewMode: String,
          comments: Object,
          isImageDiff: Boolean,
          baseImage: Object,
          revisionImage: Object,
          _builder: Object,
          _groups: Array,
          _layers: Array,
          _showTabs: Boolean,
        },

        get diffElement() {
          return this.queryEffectiveChildren('#diffTable');
        },

        observers: [
          '_groupsChanged(_groups.splices)',
        ],

        attached: function() {
          // Setup annotation layers.
          this._layers = [
            this._createTrailingWhitespaceLayer(),
            this.$.syntaxLayer,
            this._createIntralineLayer(),
            this._createTabIndicatorLayer(),
            this.$.rangeLayer,
          ];

          this.async(function() {
            this._preRenderThread();
          });
        },

        render: function(comments, prefs) {
          this.$.syntaxLayer.enabled = prefs.syntax_highlighting;
          this._showTabs = !!prefs.show_tabs;
          this._showTrailingWhitespace = !!prefs.show_whitespace_errors;

          // Stop the processor (if it's running).
          this.$.processor.cancel();
          this.$.syntaxLayer.cancel();

          this._builder = this._getDiffBuilder(this.diff, comments, prefs);

          this.$.processor.context = prefs.context;
          this.$.processor.keyLocations = this._getCommentLocations(comments);

          this._clearDiffContent();
          this._builder.addColumns(this.diffElement, prefs.font_size);

          var reporting = this.$.reporting;

          reporting.time(TimingLabel.TOTAL);
          reporting.time(TimingLabel.CONTENT);
          this.dispatchEvent(new CustomEvent('render-start', {bubbles: true}));
          return this.$.processor.process(this.diff.content).then(function() {
            if (this.isImageDiff) {
              this._builder.renderDiffImages();
            }
            this.dispatchEvent(new CustomEvent('render-content',
                {bubbles: true}));

            if (this._anyLineTooLong()) {
              this.$.syntaxLayer.enabled = false;
            }

            reporting.timeEnd(TimingLabel.CONTENT);
            reporting.time(TimingLabel.SYNTAX);
            return this.$.syntaxLayer.process().then(function() {
              reporting.timeEnd(TimingLabel.SYNTAX);
              reporting.timeEnd(TimingLabel.TOTAL);
              this.dispatchEvent(new CustomEvent('render', {bubbles: true}));
            }.bind(this));
          }.bind(this));
        },

        getLineElByChild: function(node) {
          while (node) {
            if (node instanceof Element) {
              if (node.classList.contains('lineNum')) {
                return node;
              }
              if (node.classList.contains('section')) {
                return null;
              }
            }
            node = node.previousSibling || node.parentElement;
          }
          return null;
        },

        getLineNumberByChild: function(node) {
          var lineEl = this.getLineElByChild(node);
          return lineEl ?
              parseInt(lineEl.getAttribute('data-value'), 10) : null;
        },

        getContentByLine: function(lineNumber, opt_side, opt_root) {
          return this._builder.getContentByLine(lineNumber, opt_side, opt_root);
        },

        getContentByLineEl: function(lineEl) {
          var root = Polymer.dom(lineEl.parentElement);
          var side = this.getSideByLineEl(lineEl);
          var line = lineEl.getAttribute('data-value');
          return this.getContentByLine(line, side, root);
        },

        getLineElByNumber: function(lineNumber, opt_side) {
          var sideSelector = !!opt_side ? ('.' + opt_side) : '';
          return this.diffElement.querySelector(
              '.lineNum[data-value="' + lineNumber + '"]' + sideSelector);
        },

        getContentsByLineRange: function(startLine, endLine, opt_side) {
          var result = [];
          this._builder.findLinesByRange(startLine, endLine, opt_side, null,
              result);
          return result;
        },

        getSideByLineEl: function(lineEl) {
          return lineEl.classList.contains(GrDiffBuilder.Side.RIGHT) ?
              GrDiffBuilder.Side.RIGHT : GrDiffBuilder.Side.LEFT;
        },

        createCommentThreadGroup: function(changeNum, patchNum, path,
            isOnParent, commentSide, projectConfig) {
          return this._builder.createCommentThreadGroup(changeNum, patchNum,
              path, isOnParent, commentSide, projectConfig);
        },

        emitGroup: function(group, sectionEl) {
          this._builder.emitGroup(group, sectionEl);
        },

        showContext: function(newGroups, sectionEl) {
          var groups = this._builder.groups;
          // TODO(viktard): Polyfill findIndex for IE10.
          var contextIndex = groups.findIndex(function(group) {
            return group.element == sectionEl;
          });
          groups.splice.apply(groups, [contextIndex, 1].concat(newGroups));

          newGroups.forEach(function(newGroup) {
            this._builder.emitGroup(newGroup, sectionEl);
          }, this);
          sectionEl.parentNode.removeChild(sectionEl);

          this.async(function() {
            this.fire('render');
          }, 1);
        },

        _getDiffBuilder: function(diff, comments, prefs) {
          if (this.isImageDiff) {
            return new GrDiffBuilderImage(diff, comments, prefs,
                this.diffElement, this.baseImage, this.revisionImage);
          } else if (this.viewMode === DiffViewMode.SIDE_BY_SIDE) {
            return new GrDiffBuilderSideBySide(
                diff, comments, prefs, this.diffElement, this._layers);
          } else if (this.viewMode === DiffViewMode.UNIFIED) {
            return new GrDiffBuilderUnified(
                diff, comments, prefs, this.diffElement, this._layers);
          }
          throw Error('Unsupported diff view mode: ' + this.viewMode);
        },

        _clearDiffContent: function() {
          this.diffElement.innerHTML = null;
        },

        _getCommentLocations: function(comments) {
          var result = {
            left: {},
            right: {},
          };
          for (var side in comments) {
            if (side !== GrDiffBuilder.Side.LEFT &&
                side !== GrDiffBuilder.Side.RIGHT) {
              continue;
            }
            comments[side].forEach(function(c) {
              result[side][c.line || GrDiffLine.FILE] = true;
            });
          }
          return result;
        },

        _groupsChanged: function(changeRecord) {
          if (!changeRecord) { return; }
          changeRecord.indexSplices.forEach(function(splice) {
            var group;
            for (var i = 0; i < splice.addedCount; i++) {
              group = splice.object[splice.index + i];
              this._builder.groups.push(group);
              this._builder.emitGroup(group);
            }
          }, this);
        },

        _createIntralineLayer: function() {
          return {
            // Take a DIV.contentText element and a line object with intraline
            // differences to highlight and apply them to the element as
            // annotations.
            annotate: function(el, line) {
              var HL_CLASS = 'style-scope gr-diff intraline';
              line.highlights.forEach(function(highlight) {
                // 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 (highlight.startIndex === highlight.endIndex) { return; }

                // If endIndex isn't present, continue to the end of the line.
                var endIndex = highlight.endIndex === undefined ?
                    line.text.length : highlight.endIndex;

                GrAnnotation.annotateElement(
                    el,
                    highlight.startIndex,
                    endIndex - highlight.startIndex,
                    HL_CLASS);
              });
            },
          };
        },

        _createTabIndicatorLayer: function() {
          var show = function() { return this._showTabs; }.bind(this);
          return {
            annotate: function(el, line) {
              // If visible tabs are disabled, do nothing.
              if (!show()) { return; }

              // Find and annotate the locations of tabs.
              var split = line.text.split('\t');
              if (!split) { return; }
              for (var i = 0, pos = 0; i < split.length - 1; i++) {
                // Skip forward by the length of the content
                pos += split[i].length;

                GrAnnotation.annotateElement(el, pos, 1,
                    'style-scope gr-diff tab-indicator');

                // Skip forward by one tab character.
                pos++;
              }
            },
          };
        },

        _createTrailingWhitespaceLayer: function() {
          var show = function() {
            return this._showTrailingWhitespace;
          }.bind(this);

          return {
            annotate: function(el, line) {
              if (!show()) { return; }

              var match = line.text.match(TRAILING_WHITESPACE_PATTERN);
              if (match) {
                // Normalize string positions in case there is unicode before or
                // within the match.
                var index = GrAnnotation.getStringLength(
                    line.text.substr(0, match.index));
                var length = GrAnnotation.getStringLength(match[0]);
                GrAnnotation.annotateElement(el, index, length,
                    'style-scope gr-diff trailing-whitespace');
              }
            },
          };
        },

        /**
         * In pages with large diffs, creating the first comment thread can be
         * slow because nested Polymer elements (particularly
         * iron-autogrow-textarea) add style elements to the document head,
         * which, in turn, triggers a reflow on the page. Create a hidden
         * thread, attach it to the page, and remove it so the stylesheet will
         * already exist and the user's comment will be quick to load.
         * @see https://gerrit-review.googlesource.com/c/82213/
         */
        _preRenderThread: function() {
          var thread = document.createElement('gr-diff-comment-thread');
          thread.setAttribute('hidden', true);
          thread.addDraft();
          var parent = Polymer.dom(this.root);
          parent.appendChild(thread);
          Polymer.dom.flush();
          parent.removeChild(thread);
        },

        /**
         * @return {Boolean} whether any of the lines in _groups are longer
         * than SYNTAX_MAX_LINE_LENGTH.
         */
        _anyLineTooLong: function() {
          return this._groups.reduce(function(acc, group) {
            return acc || group.lines.reduce(function(acc, line) {
              return acc || line.text.length >= SYNTAX_MAX_LINE_LENGTH;
            }, false);
          }, false);
        },
      });
    })();
  </script>
</dom-module>
