<!--
@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.
-->
<link rel="import" href="../../../bower_components/polymer/polymer.html">
<link rel="import" href="../../core/gr-reporting/gr-reporting.html">
<link rel="import" href="../../shared/gr-js-api-interface/gr-js-api-interface.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">
      <slot></slot>
    </div>
    <gr-ranged-comment-layer
        id="rangeLayer"
        comment-ranges="[[commentRanges]]"></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>
    <gr-js-api-interface id="jsAPI"></gr-js-api-interface>
  </template>
  <script src="../../../scripts/util.js"></script>
  <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 src="gr-diff-builder-binary.js"></script>
  <script>
    (function() {
      'use strict';

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

      const 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.
      const SYNTAX_MAX_LINE_LENGTH = 500;

      // Disable syntax highlighting if the overall diff is too large.
      const SYNTAX_MAX_DIFF_LENGTH = 20000;

      const TRAILING_WHITESPACE_PATTERN = /\s+$/;

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

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

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

        properties: {
          diff: Object,
          diffPath: String,
          changeNum: String,
          patchNum: String,
          viewMode: String,
          isImageDiff: Boolean,
          baseImage: Object,
          revisionImage: Object,
          parentIndex: Number,
          path: String,
          projectName: String,

          _builder: Object,
          _groups: Array,
          _layers: Array,
          _showTabs: Boolean,
          /** @type {!Array<!Gerrit.HoveredRange>} */
          commentRanges: {
            type: Array,
            value: () => [],
          },
          /**
           * The promise last returned from `render()` while the asynchronous
           * rendering is running - `null` otherwise. Provides a `cancel()`
           * method that rejects it with `{isCancelled: true}`.
           * @type {?Object}
           */
          _cancelableRenderPromise: Object,
        },

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

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

        render(keyLocations, prefs) {
          // Setting up annotation layers must happen after plugins are
          // installed, and |render| satisfies the requirement, however,
          // |attached| doesn't because in the diff view page, the element is
          // attached before plugins are installed.
          this._setupAnnotationLayers();

          this.$.syntaxLayer.enabled = prefs.syntax_highlighting;
          this._showTabs = !!prefs.show_tabs;
          this._showTrailingWhitespace = !!prefs.show_whitespace_errors;

          // Stop the processor and syntax layer (if they're running).
          this.cancel();

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

          this.$.processor.context = prefs.context;
          this.$.processor.keyLocations = keyLocations;

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

          const reporting = this.$.reporting;
          const isBinary = !!(this.isImageDiff || this.diff.binary);

          reporting.time(TimingLabel.TOTAL);
          reporting.time(TimingLabel.CONTENT);
          this.dispatchEvent(new CustomEvent('render-start', {bubbles: true}));
          this._cancelableRenderPromise = util.makeCancelable(
              this.$.processor.process(this.diff.content, isBinary)
                  .then(() => {
                    if (this.isImageDiff) {
                      this._builder.renderDiff();
                    }
                    this.dispatchEvent(new CustomEvent('render-content',
                        {bubbles: true}));

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

                    reporting.timeEnd(TimingLabel.CONTENT);
                    reporting.time(TimingLabel.SYNTAX);
                    return this.$.syntaxLayer.process();
                  })
                  .then(() => {
                    reporting.timeEnd(TimingLabel.SYNTAX);
                    reporting.timeEnd(TimingLabel.TOTAL);
                  }));
          return this._cancelableRenderPromise
              .finally(() => { this._cancelableRenderPromise = null; })
              // Mocca testing does not like uncaught rejections, so we catch
              // the cancels which are expected and should not throw errors in
              // tests.
              .catch(e => { if (!e.isCanceled) return Promise.reject(e); });
        },

        _setupAnnotationLayers() {
          const layers = [
            this._createTrailingWhitespaceLayer(),
            this.$.syntaxLayer,
            this._createIntralineLayer(),
            this._createTabIndicatorLayer(),
            this.$.rangeLayer,
          ];

          // Get layers from plugins (if any).
          for (const pluginLayer of this.$.jsAPI.getDiffLayers(
              this.diffPath, this.changeNum, this.patchNum)) {
            layers.push(pluginLayer);
          }

          this._layers = layers;
        },

        getLineElByChild(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(node) {
          const lineEl = this.getLineElByChild(node);
          return lineEl ?
              parseInt(lineEl.getAttribute('data-value'), 10) :
              null;
        },

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

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

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

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

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

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

        showContext(newGroups, sectionEl) {
          const groups = this._builder.groups;

          const contextIndex = groups.findIndex(group =>
            group.element === sectionEl
          );
          groups.splice(...[contextIndex, 1].concat(newGroups));

          for (const newGroup of newGroups) {
            this._builder.emitGroup(newGroup, sectionEl);
          }
          sectionEl.parentNode.removeChild(sectionEl);

          this.async(() => this.fire('render-content'), 1);
        },

        cancel() {
          this.$.processor.cancel();
          this.$.syntaxLayer.cancel();
          if (this._cancelableRenderPromise) {
            this._cancelableRenderPromise.cancel();
            this._cancelableRenderPromise = null;
          }
        },

        _handlePreferenceError(pref) {
          const message = `The value of the '${pref}' user preference is ` +
              `invalid. Fix in diff preferences`;
          this.dispatchEvent(new CustomEvent('show-alert', {
            detail: {
              message,
            }, bubbles: true}));
          throw Error(`Invalid preference value: ${pref}`);
        },

        _getDiffBuilder(diff, prefs) {
          if (isNaN(prefs.tab_size) || prefs.tab_size <= 0) {
            this._handlePreferenceError('tab size');
            return;
          }

          if (isNaN(prefs.line_length) || prefs.line_length <= 0) {
            this._handlePreferenceError('diff width');
            return;
          }

          let builder = null;
          if (this.isImageDiff) {
            builder = new GrDiffBuilderImage(diff, prefs, this.diffElement,
              this.baseImage, this.revisionImage);
          } else if (diff.binary) {
            // If the diff is binary, but not an image.
            return new GrDiffBuilderBinary(diff, prefs, this.diffElement);
          } else if (this.viewMode === DiffViewMode.SIDE_BY_SIDE) {
            builder = new GrDiffBuilderSideBySide(diff, prefs, this.diffElement,
                this._layers);
          } else if (this.viewMode === DiffViewMode.UNIFIED) {
            builder = new GrDiffBuilderUnified(diff, prefs, this.diffElement,
                this._layers);
          }
          if (!builder) {
            throw Error('Unsupported diff view mode: ' + this.viewMode);
          }
          return builder;
        },

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

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

        _createIntralineLayer() {
          return {
            // Take a DIV.contentText element and a line object with intraline
            // differences to highlight and apply them to the element as
            // annotations.
            annotate(contentEl, lineNumberEl, line) {
              const HL_CLASS = 'style-scope gr-diff intraline';
              for (const highlight of line.highlights) {
                // 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) { continue; }

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

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

        _createTabIndicatorLayer() {
          const show = () => this._showTabs;
          return {
            annotate(contentEl, lineNumberEl, line) {
              // If visible tabs are disabled, do nothing.
              if (!show()) { return; }

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

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

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

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

          return {
            annotate(contentEl, lineNumberEl, line) {
              if (!show()) { return; }

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

        /**
         * @return {boolean} whether any of the lines in _groups are longer
         * than SYNTAX_MAX_LINE_LENGTH.
         */
        _anyLineTooLong() {
          return this._groups.reduce((acc, group) => {
            return acc || group.lines.reduce((acc, line) => {
              return acc || line.text.length >= SYNTAX_MAX_LINE_LENGTH;
            }, false);
          }, false);
        },

        _diffTooLargeForSyntax() {
          return this._anyLineTooLong() ||
              this.getDiffLength() > SYNTAX_MAX_DIFF_LENGTH;
        },

        setBlame(blame) {
          if (!this._builder || !blame) { return; }
          this._builder.setBlame(blame);
        },

        /**
         * Get the approximate length of the diff as the sum of the maximum
         * length of the chunks.
         * @return {number}
         */
        getDiffLength() {
          return this.diff.content.reduce((sum, sec) => {
            if (sec.hasOwnProperty('ab')) {
              return sum + sec.ab.length;
            } else {
              return sum + Math.max(
                  sec.hasOwnProperty('a') ? sec.a.length : 0,
                  sec.hasOwnProperty('b') ? sec.b.length : 0);
            }
          }, 0);
        },
      });
    })();
  </script>
</dom-module>
