<!--
@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="../../../behaviors/fire-behavior/fire-behavior.html">
<link rel="import" href="../../shared/gr-js-api-interface/gr-js-api-interface.html">
<link rel="import" href="../gr-coverage-layer/gr-coverage-layer.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-coverage-layer
        id="coverageLayerLeft"
        coverage-ranges="[[_leftCoverageRanges]]"
        side="left"></gr-coverage-layer>
    <gr-coverage-layer
        id="coverageLayerRight"
        coverage-ranges="[[_rightCoverageRanges]]"
        side="right"></gr-coverage-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: () => [],
          },
          /** @type {!Array<!Gerrit.CoverageRange>} */
          coverageRanges: {
            type: Array,
            value: () => [],
          },
          _leftCoverageRanges: {
            type: Array,
            computed: '_computeLeftCoverageRanges(coverageRanges)',
          },
          _rightCoverageRanges: {
            type: Array,
            computed: '_computeRightCoverageRanges(coverageRanges)',
          },
          /**
           * 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,
          pluginLayers: {
            type: Array,
            value: [],
          },
        },

        behaviors: [
          Gerrit.FireBehavior,
        ],

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

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

        _computeLeftCoverageRanges(coverageRanges) {
          return coverageRanges.filter(range => range && range.side === 'left');
        },

        _computeRightCoverageRanges(coverageRanges) {
          return coverageRanges.filter(range => range && range.side === 'right');
        },

        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, composed: 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, composed: true}));

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

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

          if (this.pluginLayers) {
            layers.push(...this.pluginLayers);
          }
          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, ...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, composed: 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>
