<!--
@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="../../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-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',
      };

      // 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',
        _legacyUndefinedCheck: true,

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

        /**
         * Fired when the diff finishes rendering text content and starts
         * syntax highlighting.
         *
         * @event render-content
         */

        /**
         * Fired when the diff finishes syntax highlighting.
         *
         * @event render-syntax
         */

        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 isBinary = !!(this.isImageDiff || this.diff.binary);

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

                    return this.$.syntaxLayer.process();
                  })
                  .then(() => {
                    this.dispatchEvent(
                        new CustomEvent('render-syntax', {bubbles: true}));
                  }));
          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>
