/*
 * Copyright (C) 2011 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.
 */

/**
 * @param {string} mimeType
 * @return {function(string, function(string, ?string, number, number):(!Object|undefined))}
 */
export function createTokenizer(mimeType) {
  const mode = CodeMirror.getMode({indentUnit: 2}, mimeType);
  const state = CodeMirror.startState(mode);
  /**
   * @param {string} line
   * @param {function(string, ?string, number, number):?} callback
   */
  function tokenize(line, callback) {
    const stream = new CodeMirror.StringStream(line);
    while (!stream.eol()) {
      const style = mode.token(stream, state);
      const value = stream.current();
      if (callback(value, style, stream.start, stream.start + value.length) === AbortTokenization) {
        return;
      }
      stream.start = stream.pos;
    }
  }
  return tokenize;
}

export const AbortTokenization = {};

self.onmessage = function(event) {
  const method = /** @type {string} */ (event.data.method);
  const params = /** @type !{indentString: string, content: string, mimeType: string} */ (event.data.params);
  if (!method) {
    return;
  }

  switch (method) {
    case 'format':
      format(params.mimeType, params.content, params.indentString);
      break;
    case 'parseCSS':
      FormatterWorker.parseCSS(params.content);
      break;
    case 'parseSCSS':
      FormatterWorkerContentParser.parse(params.content, 'text/x-scss');
      break;
    case 'javaScriptOutline':
      FormatterWorker.javaScriptOutline(params.content);
      break;
    case 'javaScriptIdentifiers':
      javaScriptIdentifiers(params.content);
      break;
    case 'evaluatableJavaScriptSubstring':
      evaluatableJavaScriptSubstring(params.content);
      break;
    case 'parseJSONRelaxed':
      parseJSONRelaxed(params.content);
      break;
    case 'findLastExpression':
      postMessage(findLastExpression(params.content));
      break;
    case 'findLastFunctionCall':
      postMessage(findLastFunctionCall(params.content));
      break;
    case 'argumentsList':
      postMessage(argumentsList(params.content));
      break;
    default:
      console.error('Unsupport method name: ' + method);
  }
};

/**
 * @param {string} content
 */
export function parseJSONRelaxed(content) {
  postMessage(FormatterWorker.RelaxedJSONParser.parse(content));
}

/**
 * @param {string} content
 */
export function evaluatableJavaScriptSubstring(content) {
  const tokenizer = acorn.tokenizer(content, {});
  let result = '';
  try {
    let token = tokenizer.getToken();
    while (token.type !== acorn.tokTypes.eof && FormatterWorker.AcornTokenizer.punctuator(token)) {
      token = tokenizer.getToken();
    }

    const startIndex = token.start;
    let endIndex = token.end;
    let openBracketsCounter = 0;
    while (token.type !== acorn.tokTypes.eof) {
      const isIdentifier = FormatterWorker.AcornTokenizer.identifier(token);
      const isThis = FormatterWorker.AcornTokenizer.keyword(token, 'this');
      const isString = token.type === acorn.tokTypes.string;
      if (!isThis && !isIdentifier && !isString) {
        break;
      }

      endIndex = token.end;
      token = tokenizer.getToken();
      while (FormatterWorker.AcornTokenizer.punctuator(token, '.[]')) {
        if (FormatterWorker.AcornTokenizer.punctuator(token, '[')) {
          openBracketsCounter++;
        }

        if (FormatterWorker.AcornTokenizer.punctuator(token, ']')) {
          endIndex = openBracketsCounter > 0 ? token.end : endIndex;
          openBracketsCounter--;
        }

        token = tokenizer.getToken();
      }
    }
    result = content.substring(startIndex, endIndex);
  } catch (e) {
    console.error(e);
  }
  postMessage(result);
}

/**
 * @param {string} content
 */
export function javaScriptIdentifiers(content) {
  let root = null;
  try {
    root = acorn.parse(content, {ranges: false});
  } catch (e) {
  }

  /** @type {!Array<!ESTree.Node>} */
  const identifiers = [];
  const walker = new FormatterWorker.ESTreeWalker(beforeVisit);

  /**
   * @param {!ESTree.Node} node
   * @return {boolean}
   */
  function isFunction(node) {
    return node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression' ||
        node.type === 'ArrowFunctionExpression';
  }

  /**
   * @param {!ESTree.Node} node
   */
  function beforeVisit(node) {
    if (isFunction(node)) {
      if (node.id) {
        identifiers.push(node.id);
      }
      return FormatterWorker.ESTreeWalker.SkipSubtree;
    }

    if (node.type !== 'Identifier') {
      return;
    }

    if (node.parent && node.parent.type === 'MemberExpression' && node.parent.property === node &&
        !node.parent.computed) {
      return;
    }
    identifiers.push(node);
  }

  if (!root || root.type !== 'Program' || root.body.length !== 1 || !isFunction(root.body[0])) {
    postMessage([]);
    return;
  }

  const functionNode = root.body[0];
  for (const param of functionNode.params) {
    walker.walk(param);
  }
  walker.walk(functionNode.body);
  const reduced = identifiers.map(id => ({name: id.name, offset: id.start}));
  postMessage(reduced);
}

/**
 * @param {string} mimeType
 * @param {string} text
 * @param {string=} indentString
 */
export function format(mimeType, text, indentString) {
  // Default to a 4-space indent.
  indentString = indentString || '    ';
  const result = {};
  const builder = new FormatterWorker.FormattedContentBuilder(indentString);
  const lineEndings = text.computeLineEndings();
  try {
    switch (mimeType) {
      case 'text/html': {
        const formatter = new FormatterWorker.HTMLFormatter(builder);
        formatter.format(text, lineEndings);
        break;
      }
      case 'text/css': {
        const formatter = new FormatterWorker.CSSFormatter(builder);
        formatter.format(text, lineEndings, 0, text.length);
        break;
      }
      case 'text/javascript': {
        const formatter = new FormatterWorker.JavaScriptFormatter(builder);
        formatter.format(text, lineEndings, 0, text.length);
        break;
      }
      default: {
        const formatter = new FormatterWorker.IdentityFormatter(builder);
        formatter.format(text, lineEndings, 0, text.length);
      }
    }
    result.mapping = builder.mapping();
    result.content = builder.content();
  } catch (e) {
    console.error(e);
    result.mapping = {original: [0], formatted: [0]};
    result.content = text;
  }
  postMessage(result);
}

/**
 * @param {string} content
 * @return {?{baseExpression: string, possibleSideEffects:boolean, receiver: string, argumentIndex: number, functionName: string}}
 */
export function findLastFunctionCall(content) {
  if (content.length > 10000) {
    return null;
  }
  try {
    const tokenizer = acorn.tokenizer(content, {});
    while (tokenizer.getToken().type !== acorn.tokTypes.eof) {
    }
  } catch (e) {
    return null;
  }

  const suffix = '000)';
  const base = _lastCompleteExpression(content, suffix, new Set(['CallExpression', 'NewExpression']));
  if (!base) {
    return null;
  }
  const callee = base.baseNode['callee'];

  let functionName = '';
  const functionProperty = callee.type === 'Identifier' ? callee : callee.property;
  if (functionProperty) {
    if (functionProperty.type === 'Identifier') {
      functionName = functionProperty.name;
    } else if (functionProperty.type === 'Literal') {
      functionName = functionProperty.value;
    }
  }

  const argumentIndex = base.baseNode['arguments'].length - 1;
  const baseExpression =
      `(${base.baseExpression.substring(callee.start - base.baseNode.start, callee.end - base.baseNode.start)})`;
  const possibleSideEffects = _nodeHasPossibleSideEffects(callee);
  let receiver = '(function(){return this})()';
  if (callee.type === 'MemberExpression') {
    const receiverBase = callee['object'];
    receiver =
        base.baseExpression.substring(receiverBase.start - base.baseNode.start, receiverBase.end - base.baseNode.start);
  }
  return {baseExpression, receiver, possibleSideEffects, argumentIndex, functionName};
}

/**
 * @param {string} content
 * @return {!Array<string>}
 */
export function argumentsList(content) {
  if (content.length > 10000) {
    return [];
  }
  let parsed = null;
  try {
    // Try to parse as a function, anonymous function, or arrow function.
    parsed = acorn.parse(`(${content})`, {});
  } catch (e) {
  }
  if (!parsed) {
    try {
      // Try to parse as a method.
      parsed = acorn.parse(`({${content}})`, {});
    } catch (e) {
    }
  }
  if (!parsed || !parsed.body || !parsed.body[0] || !parsed.body[0].expression) {
    return [];
  }
  const expression = parsed.body[0].expression;
  let params = null;
  switch (expression.type) {
    case 'ClassExpression':
      if (!expression.body.body) {
        break;
      }
      const constructor = expression.body.body.find(method => method.kind === 'constructor');
      if (constructor) {
        params = constructor.value.params;
      }
      break;
    case 'ObjectExpression':
      if (!expression.properties[0] || !expression.properties[0].value) {
        break;
      }
      params = expression.properties[0].value.params;
      break;
    case 'FunctionExpression':
    case 'ArrowFunctionExpression':
      params = expression.params;
      break;
  }
  if (!params) {
    return [];
  }
  return params.map(paramName);

  function paramName(param) {
    switch (param.type) {
      case 'Identifier':
        return param.name;
      case 'AssignmentPattern':
        return '?' + paramName(param.left);
      case 'ObjectPattern':
        return 'obj';
      case 'ArrayPattern':
        return 'arr';
      case 'RestElement':
        return '...' + paramName(param.argument);
    }
    return '?';
  }
}

/**
 * @param {string} content
 * @return {?{baseExpression: string, possibleSideEffects:boolean}}
 */
export function findLastExpression(content) {
  if (content.length > 10000) {
    return null;
  }
  try {
    const tokenizer = acorn.tokenizer(content, {});
    while (tokenizer.getToken().type !== acorn.tokTypes.eof) {
    }
  } catch (e) {
    return null;
  }

  const suffix = '.DEVTOOLS';
  try {
    acorn.parse(content + suffix, {});
  } catch (parseError) {
    // If this is an invalid location for a '.', don't attempt to give autocomplete
    if (parseError.message.startsWith('Unexpected token') && parseError.pos === content.length) {
      return null;
    }
  }
  const base = _lastCompleteExpression(content, suffix, new Set(['MemberExpression', 'Identifier']));
  if (!base) {
    return null;
  }
  const {baseExpression, baseNode} = base;
  const possibleSideEffects = _nodeHasPossibleSideEffects(baseNode);
  return {baseExpression, possibleSideEffects};
}

/**
 * @param {string} content
 * @param {string} suffix
 * @param {!Set<string>} types
 * @return {?{baseNode: !ESTree.Node, baseExpression: string}}
 */
export function _lastCompleteExpression(content, suffix, types) {
  /** @type {!ESTree.Node} */
  let ast;
  let parsedContent = '';
  for (let i = 0; i < content.length; i++) {
    try {
      // Wrap content in paren to successfully parse object literals
      parsedContent = content[i] === '{' ? `(${content.substring(i)})${suffix}` : `${content.substring(i)}${suffix}`;
      ast = acorn.parse(parsedContent, {});
      break;
    } catch (e) {
    }
  }
  if (!ast) {
    return null;
  }
  let baseNode = null;
  const walker = new FormatterWorker.ESTreeWalker(node => {
    if (baseNode || node.end < ast.end) {
      return FormatterWorker.ESTreeWalker.SkipSubtree;
    }
    if (types.has(node.type)) {
      baseNode = node;
    }
  });
  walker.walk(ast);
  if (!baseNode) {
    return null;
  }
  let baseExpression = parsedContent.substring(baseNode.start, parsedContent.length - suffix.length);
  if (baseExpression.startsWith('{')) {
    baseExpression = `(${baseExpression})`;
  }
  return {baseNode, baseExpression};
}

/**
 * @param {!ESTree.Node} baseNode
 * @return {boolean}
 */
export function _nodeHasPossibleSideEffects(baseNode) {
  const sideEffectFreeTypes = new Set([
    'MemberExpression', 'Identifier', 'BinaryExpression', 'Literal', 'TemplateLiteral', 'TemplateElement',
    'ObjectExpression', 'ArrayExpression', 'Property', 'ThisExpression'
  ]);
  let possibleSideEffects = false;
  const sideEffectwalker = new FormatterWorker.ESTreeWalker(node => {
    if (!possibleSideEffects && !sideEffectFreeTypes.has(node.type)) {
      possibleSideEffects = true;
    }
    if (possibleSideEffects) {
      return FormatterWorker.ESTreeWalker.SkipSubtree;
    }
  });
  sideEffectwalker.walk(/** @type {!ESTree.Node} */ (baseNode));
  return possibleSideEffects;
}

/**
 * @interface
 */
export class FormatterWorkerContentParser {
  /**
   * @param {string} content
   * @return {!Object}
   */
  parse(content) {}
}

/**
 * @param {string} content
 * @param {string} mimeType
 */
FormatterWorkerContentParser.parse = function(content, mimeType) {
  const extension = self.runtime.extensions(FormatterWorkerContentParser).find(findExtension);
  console.assert(extension);
  extension.instance().then(instance => instance.parse(content)).catchException(null).then(postMessage);

  /**
   * @param {!Root.Runtime.Extension} extension
   * @return {boolean}
   */
  function findExtension(extension) {
    return extension.descriptor()['mimeType'] === mimeType;
  }
};

(function disableLoggingForTest() {
  if (Root.Runtime.queryParam('test')) {
    console.error = () => undefined;
  }
})();

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

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

FormatterWorker.AbortTokenization = AbortTokenization;
FormatterWorker.createTokenizer = createTokenizer;
FormatterWorker.parseJSONRelaxed = parseJSONRelaxed;
FormatterWorker.evaluatableJavaScriptSubstring = evaluatableJavaScriptSubstring;
FormatterWorker.javaScriptIdentifiers = javaScriptIdentifiers;
FormatterWorker.format = format;
FormatterWorker.findLastFunctionCall = findLastFunctionCall;
FormatterWorker.argumentsList = argumentsList;
FormatterWorker.findLastExpression = findLastExpression;
FormatterWorker._lastCompleteExpression = _lastCompleteExpression;
FormatterWorker._nodeHasPossibleSideEffects = _nodeHasPossibleSideEffects;
FormatterWorker.FormatterWorkerContentParser = FormatterWorkerContentParser;
