/**
 * @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.
 */
import '../gr-coverage-layer/gr-coverage-layer.js';
import '../gr-diff-processor/gr-diff-processor.js';
import '../../shared/gr-hovercard/gr-hovercard.js';
import '../gr-ranged-comment-layer/gr-ranged-comment-layer.js';
import './gr-diff-builder-side-by-side.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners.js';
import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin.js';
import {PolymerElement} from '@polymer/polymer/polymer-element.js';
import {htmlTemplate} from './gr-diff-builder-element_html.js';
import {GrAnnotation} from '../gr-diff-highlight/gr-annotation.js';
import {GrDiffBuilder} from './gr-diff-builder.js';
import {GrDiffBuilderSideBySide} from './gr-diff-builder-side-by-side.js';
import {GrDiffBuilderImage} from './gr-diff-builder-image.js';
import {GrDiffBuilderUnified} from './gr-diff-builder-unified.js';
import {GrDiffBuilderBinary} from './gr-diff-builder-binary.js';
import {util} from '../../../scripts/util.js';

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

const TRAILING_WHITESPACE_PATTERN = /\s+$/;

// https://gerrit.googlesource.com/gerrit/+/234616a8627334686769f1de989d286039f4d6a5/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.js#740
const COMMIT_MSG_PATH = '/COMMIT_MSG';
const COMMIT_MSG_LINE_LENGTH = 72;

/**
 * @extends PolymerElement
 */
class GrDiffBuilderElement extends GestureEventListeners(
    LegacyElementMixin(PolymerElement)) {
  static get template() { return htmlTemplate; }

  static get is() { return 'gr-diff-builder'; }
  /**
   * Fired when the diff begins rendering.
   *
   * @event render-start
   */

  /**
   * Fired when the diff finishes rendering text content.
   *
   * @event render-content
   */

  static get properties() {
    return {
      diff: Object,
      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,
      layers: {
        type: Array,
        value: [],
      },
    };
  }

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

  static get observers() {
    return [
      '_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._showTabs = !!prefs.show_tabs;
    this._showTrailingWhitespace = !!prefs.show_whitespace_errors;

    // Stop the processor if it's 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}));
            }));
    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._createIntralineLayer(),
      this._createTabIndicatorLayer(),
      this.$.rangeLayer,
      this.$.coverageLayerLeft,
      this.$.coverageLayerRight,
    ];

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

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

  _getDiffRowByChild(child) {
    while (!child.classList.contains('diff-row') && child.parentElement) {
      child = child.parentElement;
    }
    return child;
  }

  getContentTdByLineEl(lineEl) {
    if (!lineEl) return;
    const line = lineEl.getAttribute('data-value');
    const side = this.getSideByLineEl(lineEl);
    // Performance optimization because we already have an element in the
    // correct row
    const row = dom(this._getDiffRowByChild(lineEl));
    return this.getContentTdByLine(line, side, row);
  }

  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.dispatchEvent(new CustomEvent('render-content', {
      composed: true, bubbles: true,
    })), 1);
  }

  cancel() {
    this.$.processor.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;
    }

    const localPrefs = Object.assign({}, prefs);
    if (this.path === COMMIT_MSG_PATH) {
      // override line_length for commit msg the same way as
      // in gr-diff
      localPrefs.line_length = COMMIT_MSG_LINE_LENGTH;
    }

    let builder = null;
    if (this.isImageDiff) {
      builder = new GrDiffBuilderImage(
          diff,
          localPrefs,
          this.diffElement,
          this.baseImage,
          this.revisionImage);
    } else if (diff.binary) {
      // If the diff is binary, but not an image.
      return new GrDiffBuilderBinary(
          diff,
          localPrefs,
          this.diffElement);
    } else if (this.viewMode === DiffViewMode.SIDE_BY_SIDE) {
      builder = new GrDiffBuilderSideBySide(
          diff,
          localPrefs,
          this.diffElement,
          this._layers
      );
    } else if (this.viewMode === DiffViewMode.UNIFIED) {
      builder = new GrDiffBuilderUnified(
          diff,
          localPrefs,
          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');
        }
      },
    };
  }

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

customElements.define(GrDiffBuilderElement.is, GrDiffBuilderElement);
