<!--
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-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',
      };

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

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

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

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

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

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

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

        render: function(comments, prefs) {
          this.$.syntaxLayer.enabled = prefs.syntax_highlighting;

          // 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();

          var reporting = this.$.reporting;

          reporting.time(TimingLabel.TOTAL);
          reporting.time(TimingLabel.CONTENT);
          return this.$.processor.process(this.diff.content).then(function() {
            if (this.isImageDiff) {
              this._builder.renderDiffImages();
            }
            reporting.timeEnd(TimingLabel.CONTENT);
            reporting.time(TimingLabel.SYNTAX);
            this.$.syntaxLayer.process().then(function() {
              reporting.timeEnd(TimingLabel.SYNTAX);
              reporting.timeEnd(TimingLabel.TOTAL);
            });
            this.fire('render');
          }.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;
        },

        renderLineRange: function(startLine, endLine, opt_side) {
          var groups =
              this._builder.getGroupsByLineRange(startLine, endLine, opt_side);
          groups.forEach(function(group) {
            var newElement = this._builder.buildSectionElement(group);
            var oldElement = group.element;

            // Transfer comment threads from existing section to new one.
            var threads = Polymer.dom(newElement).querySelectorAll(
                'gr-diff-comment-thread');
            threads.forEach(function(threadEl) {
              var lineEl = this.getLineElByChild(threadEl, oldElement);
              if (!lineEl) { // New comment thread.
                return;
              }
              var side = this.getSideByLineEl(lineEl);
              var line = lineEl.getAttribute('data-value');
              var oldThreadEl =
                  this.getCommentThreadByLine(line, side, oldElement);
              threadEl.parentNode.replaceChild(oldThreadEl, threadEl);
            }, this);

            // Replace old group elements with new ones.
            group.element.parentNode.replaceChild(newElement, group.element);
            group.element = newElement;
          }, this);

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

        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;
        },

        getCommentThreadByLine: function(lineNumber, opt_side, opt_root) {
          var content = this.getContentByLine(lineNumber, opt_side, opt_root);
          return this.getCommentThreadByContentEl(content);
        },

        getCommentThreadByContentEl: function(contentEl) {
          if (contentEl.classList.contains('contentText')) {
            contentEl = contentEl.parentElement;
          }
          return contentEl.querySelector('gr-diff-comment-thread');
        },

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

        createCommentThread: function(changeNum, patchNum, path, side,
            projectConfig) {
          return this._builder.createCommentThread(changeNum, patchNum, path,
              side, 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 {
            addListener: function() {},

            // 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);
              });
            },
          };
        },

        /**
         * 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);
        },
      });
    })();
  </script>
</dom-module>
