// 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.
(function() {
  'use strict';

  var LANGUAGE_MAP = {
    'application/dart': 'dart',
    'application/json': 'json',
    'application/typescript': 'typescript',
    'text/css': 'css',
    'text/html': 'html',
    'text/javascript': 'js',
    'text/x-c': 'cpp',
    'text/x-c++src': 'cpp',
    'text/x-clojure': 'clojure',
    'text/x-common-lisp': 'lisp',
    'text/x-csharp': 'csharp',
    'text/x-csrc': 'cpp',
    'text/x-d': 'd',
    'text/x-go': 'go',
    'text/x-haskell': 'haskell',
    'text/x-java': 'java',
    'text/x-lua': 'lua',
    'text/x-markdown': 'markdown',
    'text/x-objectivec': 'objectivec',
    'text/x-ocaml': 'ocaml',
    'text/x-perl': 'perl',
    'text/x-protobuf': 'protobuf',
    'text/x-python': 'python',
    'text/x-ruby': 'ruby',
    'text/x-rustsrc': 'rust',
    'text/x-scala': 'scala',
    'text/x-sh': 'bash',
    'text/x-sql': 'sql',
    'text/x-swift': 'swift',
    'text/x-yaml': 'yaml',
  };
  var ASYNC_DELAY = 10;

  var CLASS_WHITELIST = {
    'gr-diff gr-syntax gr-syntax-literal': true,
    'gr-diff gr-syntax gr-syntax-keyword': true,
    'gr-diff gr-syntax gr-syntax-selector-tag': true,
    'gr-diff gr-syntax gr-syntax-built_in': true,
    'gr-diff gr-syntax gr-syntax-type': true,
    'gr-diff gr-syntax gr-syntax-selector-pseudo': true,
    'gr-diff gr-syntax gr-syntax-template-variable': true,
    'gr-diff gr-syntax gr-syntax-number': true,
    'gr-diff gr-syntax gr-syntax-regexp': true,
    'gr-diff gr-syntax gr-syntax-variable': true,
    'gr-diff gr-syntax gr-syntax-selector-attr': true,
    'gr-diff gr-syntax gr-syntax-template-tag': true,
    'gr-diff gr-syntax gr-syntax-string': true,
    'gr-diff gr-syntax gr-syntax-selector-id': true,
    'gr-diff gr-syntax gr-syntax-title': true,
    'gr-diff gr-syntax gr-syntax-params': true,
    'gr-diff gr-syntax gr-syntax-comment': true,
    'gr-diff gr-syntax gr-syntax-meta': true,
    'gr-diff gr-syntax gr-syntax-meta-keyword': true,
    'gr-diff gr-syntax gr-syntax-tag': true,
    'gr-diff gr-syntax gr-syntax-name': true,
    'gr-diff gr-syntax gr-syntax-attr': true,
    'gr-diff gr-syntax gr-syntax-attribute': true,
    'gr-diff gr-syntax gr-syntax-emphasis': true,
    'gr-diff gr-syntax gr-syntax-strong': true,
    'gr-diff gr-syntax gr-syntax-link': true,
    'gr-diff gr-syntax gr-syntax-selector-class': true,
  };

  var CPP_DIRECTIVE_WITH_LT_PATTERN = /^\s*#(if|define).*</;
  var JAVA_PARAM_ANNOT_PATTERN = /(@[^\s]+)\(([^)]+)\)/g;
  var GLOBAL_LT_PATTERN = /</g;

  Polymer({
    is: 'gr-syntax-layer',

    properties: {
      diff: {
        type: Object,
        observer: '_diffChanged',
      },
      enabled: {
        type: Boolean,
        value: true,
      },
      _baseRanges: {
        type: Array,
        value: function() { return []; },
      },
      _revisionRanges: {
        type: Array,
        value: function() { return []; },
      },
      _baseLanguage: String,
      _revisionLanguage: String,
      _listeners: {
        type: Array,
        value: function() { return []; },
      },
      _processHandle: Number,
      _hljs: Object,
    },

    addListener: function(fn) {
      this.push('_listeners', fn);
    },

    /**
     * Annotation layer method to add syntax annotations to the given element
     * for the given line.
     * @param {!HTMLElement} el
     * @param {!GrDiffLine} line
     */
    annotate: function(el, line) {
      if (!this.enabled) { return; }

      // Determine the side.
      var side;
      if (line.type === GrDiffLine.Type.REMOVE || (
          line.type === GrDiffLine.Type.BOTH &&
          el.getAttribute('data-side') !== 'right')) {
        side = 'left';
      } else if (line.type === GrDiffLine.Type.ADD || (
          el.getAttribute('data-side') !== 'left')) {
        side = 'right';
      }

      // Find the relevant syntax ranges, if any.
      var ranges = [];
      if (side === 'left' && this._baseRanges.length >= line.beforeNumber) {
        ranges = this._baseRanges[line.beforeNumber - 1] || [];
      } else if (side === 'right' &&
          this._revisionRanges.length >= line.afterNumber) {
        ranges = this._revisionRanges[line.afterNumber - 1] || [];
      }

      // Apply the ranges to the element.
      ranges.forEach(function(range) {
        GrAnnotation.annotateElement(
            el, range.start, range.length, range.className);
      });
    },

    /**
     * Start processing symtax for the loaded diff and notify layer listeners
     * as syntax info comes online.
     * @return {Promise}
     */
    process: function() {
      // Discard existing ranges.
      this._baseRanges = [];
      this._revisionRanges = [];

      if (!this.enabled || !this.diff.content.length) {
        return Promise.resolve();
      }

      this.cancel();

      if (this.diff.meta_a) {
        this._baseLanguage = LANGUAGE_MAP[this.diff.meta_a.content_type];
      }
      if (this.diff.meta_b) {
        this._revisionLanguage = LANGUAGE_MAP[this.diff.meta_b.content_type];
      }
      if (!this._baseLanguage && !this._revisionLanguage) {
        return Promise.resolve();
      }

      var state = {
        sectionIndex: 0,
        lineIndex: 0,
        baseContext: undefined,
        revisionContext: undefined,
        lineNums: {left: 1, right: 1},
        lastNotify: {left: 1, right: 1},
      };

      return this._loadHLJS().then(function() {
        return new Promise(function(resolve) {
          var nextStep = function() {
            this._processHandle = null;
            this._processNextLine(state);

            // Move to the next line in the section.
            state.lineIndex++;

            // If the section has been exhausted, move to the next one.
            if (this._isSectionDone(state)) {
              state.lineIndex = 0;
              state.sectionIndex++;
            }

            // If all sections have been exhausted, finish.
            if (state.sectionIndex >= this.diff.content.length) {
              resolve();
              this._notify(state);
              return;
            }

            if (state.sectionIndex !== 0 && state.lineIndex % 100 === 0) {
              this._notify(state);
              this._processHandle = this.async(nextStep, ASYNC_DELAY);
            } else {
              nextStep.call(this);
            }
          };

          this._processHandle = this.async(nextStep, 1);
        }.bind(this));
      }.bind(this));
    },

    /**
     * Cancel any asynchronous syntax processing jobs.
     */
    cancel: function() {
      if (this._processHandle) {
        this.cancelAsync(this._processHandle);
        this._processHandle = null;
      }
    },

    _diffChanged: function() {
      this.cancel();
      this._baseRanges = [];
      this._revisionRanges = [];
    },

    /**
     * Take a string of HTML with the (potentially nested) syntax markers
     * Highlight.js emits and emit a list of text ranges and classes for the
     * markers.
     * @param {string} str The string of HTML.
     * @return {!Array<!Object>} The list of ranges.
     */
    _rangesFromString: function(str) {
      var div = document.createElement('div');
      div.innerHTML = str;
      return this._rangesFromElement(div, 0);
    },

    _rangesFromElement: function(elem, offset) {
      var result = [];
      for (var i = 0; i < elem.childNodes.length; i++) {
        var node = elem.childNodes[i];
        var nodeLength = GrAnnotation.getLength(node);
        // Note: HLJS may emit a span with class undefined when it thinks there
        // may be a syntax error.
        if (node.tagName === 'SPAN' && node.className !== 'undefined') {
          if (CLASS_WHITELIST.hasOwnProperty(node.className)) {
            result.push({
              start: offset,
              length: nodeLength,
              className: node.className,
            });
          }
          if (node.children.length) {
            result = result.concat(this._rangesFromElement(node, offset));
          }
        }
        offset += nodeLength;
      }
      return result;
    },

    /**
     * For a given state, process the syntax for the next line (or pair of
     * lines).
     * @param {!Object} state The processing state for the layer.
     */
    _processNextLine: function(state) {
      var baseLine;
      var revisionLine;

      var section = this.diff.content[state.sectionIndex];
      if (section.ab) {
        baseLine = section.ab[state.lineIndex];
        revisionLine = section.ab[state.lineIndex];
        state.lineNums.left++;
        state.lineNums.right++;
      } else {
        if (section.a && section.a.length > state.lineIndex) {
          baseLine = section.a[state.lineIndex];
          state.lineNums.left++;
        }
        if (section.b && section.b.length > state.lineIndex) {
          revisionLine = section.b[state.lineIndex];
          state.lineNums.right++;
        }
      }

      // To store the result of the syntax highlighter.
      var result;

      if (this._baseLanguage && baseLine !== undefined) {
        baseLine = this._workaround(this._baseLanguage, baseLine);
        result = this._hljs.highlight(this._baseLanguage, baseLine, true,
            state.baseContext);
        this.push('_baseRanges', this._rangesFromString(result.value));
        state.baseContext = result.top;
      }

      if (this._revisionLanguage && revisionLine !== undefined) {
        revisionLine = this._workaround(this._revisionLanguage, revisionLine);
        result = this._hljs.highlight(this._revisionLanguage, revisionLine,
            true, state.revisionContext);
        this.push('_revisionRanges', this._rangesFromString(result.value));
        state.revisionContext = result.top;
      }
    },

    /**
     * Ad hoc fixes for HLJS parsing bugs. Rewrite lines of code in constrained
     * cases before sending them into HLJS so that they parse correctly.
     *
     * Important notes:
     * * These tests should be as constrained as possible to avoid interfering
     *   with code it shouldn't AND to avoid executing regexes as much as
     *   possible.
     * * These tests should document the issue clearly enough that the test can
     *   be condidently removed when the issue is solved in HLJS.
     * * These tests should rewrite the line of code to have the same number of
     *   characters. This method rewrites the string that gets parsed, but NOT
     *   the string that gets displayed and highlighted. Thus, the positions
     *   must be consistent.
     *
     * @param {!string} language The name of the HLJS language plugin in use.
     * @param {!string} line The line of code to potentially rewrite.
     * @return {string} A potentially-rewritten line of code.
     */
    _workaround: function(language, line) {
      /**
       * Prevent confusing < and << operators for the start of a meta string by
       * converting them to a different operator.
       * {@see Issue 4864}
       * {@see https://github.com/isagalaev/highlight.js/issues/1341}
       */
      if (language === 'cpp' && CPP_DIRECTIVE_WITH_LT_PATTERN.test(line)) {
        return line.replace(GLOBAL_LT_PATTERN, '|');
      }

      /**
       * Prevent confusing the closing paren of a parameterized Java annotation
       * being applied to a formal argument as the closing paren of the argument
       * list. Rewrite the parens as spaces.
       * {@see Issue 4776}
       * {@see https://github.com/isagalaev/highlight.js/issues/1324}
       */
      if (language === 'java' && JAVA_PARAM_ANNOT_PATTERN.test(line)) {
        return line.replace(JAVA_PARAM_ANNOT_PATTERN, '$1 $2 ');
      }

      return line;
    },

    /**
     * Tells whether the state has exhausted its current section.
     * @param {!Object} state
     * @return {boolean}
     */
    _isSectionDone: function(state) {
      var section = this.diff.content[state.sectionIndex];
      if (section.ab) {
        return state.lineIndex >= section.ab.length;
      } else {
        return (!section.a || state.lineIndex >= section.a.length) &&
            (!section.b || state.lineIndex >= section.b.length);
      }
    },

    /**
     * For a given state, notify layer listeners of any processed line ranges
     * that have not yet been notified.
     * @param {!Object} state
     */
    _notify: function(state) {
      if (state.lineNums.left - state.lastNotify.left) {
        this._notifyRange(
          state.lastNotify.left,
          state.lineNums.left,
          'left');
        state.lastNotify.left = state.lineNums.left;
      }
      if (state.lineNums.right - state.lastNotify.right) {
        this._notifyRange(
          state.lastNotify.right,
          state.lineNums.right,
          'right');
        state.lastNotify.right = state.lineNums.right;
      }
    },

    _notifyRange: function(start, end, side) {
      this._listeners.forEach(function(fn) {
        fn(start, end, side);
      });
    },

    _loadHLJS: function() {
      return this.$.libLoader.get().then(function(hljs) {
        this._hljs = hljs;
      }.bind(this));
    },
  });
})();
