/*
 * Copyright (C) 2013 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
const Utils = {
  /**
   * @param {string} char
   * @return {boolean}
   */
  isStopChar: function(char) {
    return (char > ' ' && char < '0') || (char > '9' && char < 'A') || (char > 'Z' && char < '_') ||
        (char > '_' && char < 'a') || (char > 'z' && char <= '~');
  },

  /**
   * @param {string} char
   * @return {boolean}
   */
  isWordChar: function(char) {
    return !TextUtils.TextUtils.isStopChar(char) && !TextUtils.TextUtils.isSpaceChar(char);
  },

  /**
   * @param {string} char
   * @return {boolean}
   */
  isSpaceChar: function(char) {
    return TextUtils.TextUtils._SpaceCharRegex.test(char);
  },

  /**
   * @param {string} word
   * @return {boolean}
   */
  isWord: function(word) {
    for (let i = 0; i < word.length; ++i) {
      if (!TextUtils.TextUtils.isWordChar(word.charAt(i))) {
        return false;
      }
    }
    return true;
  },

  /**
   * @param {string} char
   * @return {boolean}
   */
  isOpeningBraceChar: function(char) {
    return char === '(' || char === '{';
  },

  /**
   * @param {string} char
   * @return {boolean}
   */
  isClosingBraceChar: function(char) {
    return char === ')' || char === '}';
  },

  /**
   * @param {string} char
   * @return {boolean}
   */
  isBraceChar: function(char) {
    return TextUtils.TextUtils.isOpeningBraceChar(char) || TextUtils.TextUtils.isClosingBraceChar(char);
  },

  /**
   * @param {string} text
   * @param {function(string):boolean} isWordChar
   * @param {function(string)} wordCallback
   */
  textToWords: function(text, isWordChar, wordCallback) {
    let startWord = -1;
    for (let i = 0; i < text.length; ++i) {
      if (!isWordChar(text.charAt(i))) {
        if (startWord !== -1) {
          wordCallback(text.substring(startWord, i));
        }
        startWord = -1;
      } else if (startWord === -1) {
        startWord = i;
      }
    }
    if (startWord !== -1) {
      wordCallback(text.substring(startWord));
    }
  },

  /**
   * @param {string} line
   * @return {string}
   */
  lineIndent: function(line) {
    let indentation = 0;
    while (indentation < line.length && TextUtils.TextUtils.isSpaceChar(line.charAt(indentation))) {
      ++indentation;
    }
    return line.substr(0, indentation);
  },

  /**
   * @param {string} text
   * @return {boolean}
   */
  isUpperCase: function(text) {
    return text === text.toUpperCase();
  },

  /**
   * @param {string} text
   * @return {boolean}
   */
  isLowerCase: function(text) {
    return text === text.toLowerCase();
  },

  /**
   * @param {string} text
   * @param {!Array<!RegExp>} regexes
   * @return {!Array<{value: string, position: number, regexIndex: number, captureGroups: !Array<string|undefined>}>}
   */
  splitStringByRegexes(text, regexes) {
    const matches = [];
    const globalRegexes = [];
    for (let i = 0; i < regexes.length; i++) {
      const regex = regexes[i];
      if (!regex.global) {
        globalRegexes.push(new RegExp(regex.source, regex.flags ? regex.flags + 'g' : 'g'));
      } else {
        globalRegexes.push(regex);
      }
    }
    doSplit(text, 0, 0);
    return matches;

    /**
     * @param {string} text
     * @param {number} regexIndex
     * @param {number} startIndex
     */
    function doSplit(text, regexIndex, startIndex) {
      if (regexIndex >= globalRegexes.length) {
        // Set regexIndex as -1 if text did not match with any regular expression
        matches.push({value: text, position: startIndex, regexIndex: -1, captureGroups: []});
        return;
      }
      const regex = globalRegexes[regexIndex];
      let currentIndex = 0;
      let result;
      regex.lastIndex = 0;
      while ((result = regex.exec(text)) !== null) {
        const stringBeforeMatch = text.substring(currentIndex, result.index);
        if (stringBeforeMatch) {
          doSplit(stringBeforeMatch, regexIndex + 1, startIndex + currentIndex);
        }
        const match = result[0];
        matches.push({
          value: match,
          position: startIndex + result.index,
          regexIndex: regexIndex,
          captureGroups: result.slice(1)
        });
        currentIndex = result.index + match.length;
      }
      const stringAfterMatches = text.substring(currentIndex);
      if (stringAfterMatches) {
        doSplit(stringAfterMatches, regexIndex + 1, startIndex + currentIndex);
      }
    }
  }
};

export default Utils;

export class FilterParser {
  /**
   * @param {!Array<string>} keys
   */
  constructor(keys) {
    this._keys = keys;
  }

  /**
   * @param {!TextUtils.FilterParser.ParsedFilter} filter
   * @return {!TextUtils.FilterParser.ParsedFilter}
   */
  static cloneFilter(filter) {
    return {key: filter.key, text: filter.text, regex: filter.regex, negative: filter.negative};
  }

  /**
   * @param {string} query
   * @return {!Array<!TextUtils.FilterParser.ParsedFilter>}
   */
  parse(query) {
    const splitResult = TextUtils.TextUtils.splitStringByRegexes(query, [
      TextUtils.TextUtils._keyValueFilterRegex, TextUtils.TextUtils._regexFilterRegex,
      TextUtils.TextUtils._textFilterRegex
    ]);
    const filters = [];
    for (let i = 0; i < splitResult.length; i++) {
      const regexIndex = splitResult[i].regexIndex;
      if (regexIndex === -1) {
        continue;
      }
      const result = splitResult[i].captureGroups;
      if (regexIndex === 0) {
        if (this._keys.indexOf(/** @type {string} */ (result[1])) !== -1) {
          filters.push({key: result[1], text: result[2], negative: !!result[0]});
        } else {
          filters.push({text: result[1] + ':' + result[2], negative: !!result[0]});
        }
      } else if (regexIndex === 1) {
        try {
          filters.push({regex: new RegExp(result[1], 'i'), negative: !!result[0]});
        } catch (e) {
          filters.push({text: '/' + result[1] + '/', negative: !!result[0]});
        }
      } else if (regexIndex === 2) {
        filters.push({text: result[1], negative: !!result[0]});
      }
    }
    return filters;
  }
}

Utils._keyValueFilterRegex = /(?:^|\s)(\-)?([\w\-]+):([^\s]+)/;
Utils._regexFilterRegex = /(?:^|\s)(\-)?\/([^\s]+)\//;
Utils._textFilterRegex = /(?:^|\s)(\-)?([^\s]+)/;
Utils._SpaceCharRegex = /\s/;

/**
 * @enum {string}
 */
Utils.Indent = {
  TwoSpaces: '  ',
  FourSpaces: '    ',
  EightSpaces: '        ',
  TabCharacter: '\t'
};

/**
 * @unrestricted
 */
export class BalancedJSONTokenizer {
  /**
   * @param {function(string)} callback
   * @param {boolean=} findMultiple
   */
  constructor(callback, findMultiple) {
    this._callback = callback;
    this._index = 0;
    this._balance = 0;
    this._buffer = '';
    this._findMultiple = findMultiple || false;
    this._closingDoubleQuoteRegex = /[^\\](?:\\\\)*"/g;
  }

  /**
   * @param {string} chunk
   * @return {boolean}
   */
  write(chunk) {
    this._buffer += chunk;
    const lastIndex = this._buffer.length;
    const buffer = this._buffer;
    let index;
    for (index = this._index; index < lastIndex; ++index) {
      const character = buffer[index];
      if (character === '"') {
        this._closingDoubleQuoteRegex.lastIndex = index;
        if (!this._closingDoubleQuoteRegex.test(buffer)) {
          break;
        }
        index = this._closingDoubleQuoteRegex.lastIndex - 1;
      } else if (character === '{') {
        ++this._balance;
      } else if (character === '}') {
        --this._balance;
        if (this._balance < 0) {
          this._reportBalanced();
          return false;
        }
        if (!this._balance) {
          this._lastBalancedIndex = index + 1;
          if (!this._findMultiple) {
            break;
          }
        }
      } else if (character === ']' && !this._balance) {
        this._reportBalanced();
        return false;
      }
    }
    this._index = index;
    this._reportBalanced();
    return true;
  }

  _reportBalanced() {
    if (!this._lastBalancedIndex) {
      return;
    }
    this._callback(this._buffer.slice(0, this._lastBalancedIndex));
    this._buffer = this._buffer.slice(this._lastBalancedIndex);
    this._index -= this._lastBalancedIndex;
    this._lastBalancedIndex = 0;
  }

  /**
   * @return {string}
   */
  remainder() {
    return this._buffer;
  }
}

/**
 * @interface
 */
export class TokenizerFactory {
  /**
   * @param {string} mimeType
   * @return {function(string, function(string, ?string, number, number))}
   */
  createTokenizer(mimeType) {}
}

/**
 * @param {string} text
 * @return {boolean}
 */
export function isMinified(text) {
  const kMaxNonMinifiedLength = 500;
  let linesToCheck = 10;
  let lastPosition = 0;
  do {
    let eolIndex = text.indexOf('\n', lastPosition);
    if (eolIndex < 0) {
      eolIndex = text.length;
    }
    if (eolIndex - lastPosition > kMaxNonMinifiedLength && text.substr(lastPosition, 3) !== '//#') {
      return true;
    }
    lastPosition = eolIndex + 1;
  } while (--linesToCheck >= 0 && lastPosition < text.length);

  // Check the end of the text as well
  linesToCheck = 10;
  lastPosition = text.length;
  do {
    let eolIndex = text.lastIndexOf('\n', lastPosition);
    if (eolIndex < 0) {
      eolIndex = 0;
    }
    if (lastPosition - eolIndex > kMaxNonMinifiedLength && text.substr(lastPosition, 3) !== '//#') {
      return true;
    }
    lastPosition = eolIndex - 1;
  } while (--linesToCheck >= 0 && lastPosition > 0);
  return false;
}

/* Legacy exported object */
self.TextUtils = self.TextUtils || {};

/* Legacy exported object */
TextUtils = TextUtils || {};

TextUtils.TextUtils = Utils;

/** @constructor */
TextUtils.FilterParser = FilterParser;

/** @constructor */
TextUtils.BalancedJSONTokenizer = BalancedJSONTokenizer;

/** @interface */
TextUtils.TokenizerFactory = TokenizerFactory;

TextUtils.isMinified = isMinified;

/** @typedef {{key:(string|undefined), text:(?string|undefined), regex:(!RegExp|undefined), negative:boolean}} */
TextUtils.FilterParser.ParsedFilter;
