<!--
@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="../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: () => [],
          },
        },

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

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

        _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>
