// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

ObjectUI.JavaScriptAutocomplete = class {
  constructor() {
    /** @type {!Map<string, {date: number, value: !Promise<?Object>}>} */
    this._expressionCache = new Map();
    SDK.consoleModel.addEventListener(SDK.ConsoleModel.Events.CommandEvaluated, this._clearCache, this);
    UI.context.addFlavorChangeListener(SDK.ExecutionContext, this._clearCache, this);
    SDK.targetManager.addModelListener(
        SDK.DebuggerModel, SDK.DebuggerModel.Events.DebuggerResumed, this._clearCache, this);
    SDK.targetManager.addModelListener(
        SDK.DebuggerModel, SDK.DebuggerModel.Events.DebuggerPaused, this._clearCache, this);
  }

  _clearCache() {
    this._expressionCache.clear();
  }

  /**
   * @param {string} fullText
   * @param {string} query
   * @param {boolean=} force
   * @return {!Promise<!UI.SuggestBox.Suggestions>}
   */
  async completionsForTextInCurrentContext(fullText, query, force) {
    const trimmedText = fullText.trim();

    const [mapCompletions, expressionCompletions] = await Promise.all(
        [this._mapCompletions(trimmedText, query), this._completionsForExpression(trimmedText, query, force)]);
    return mapCompletions.concat(expressionCompletions);
  }

  /**
   * @param {string} fullText
   * @return {!Promise<?{args: !Array<!Array<string>>, argumentIndex: number}>}
   */
  async argumentsHint(fullText) {
    const functionCall = await Formatter.formatterWorkerPool().findLastFunctionCall(fullText);
    if (!functionCall)
      return null;
    const executionContext = UI.context.flavor(SDK.ExecutionContext);
    if (!executionContext)
      return null;
    const result = await executionContext.evaluate(
        {
          expression: functionCall.baseExpression,
          objectGroup: 'argumentsHint',
          includeCommandLineAPI: true,
          silent: true,
          returnByValue: false,
          generatePreview: false,
          throwOnSideEffect: functionCall.possibleSideEffects,
          timeout: functionCall.possibleSideEffects ? 500 : undefined
        },
        /* userGesture */ false, /* awaitPromise */ false);
    if (!result || result.exceptionDetails || !result.object || result.object.type !== 'function') {
      executionContext.runtimeModel.releaseObjectGroup('argumentsHint');
      return null;
    }

    const args = await this._argumentsForFunction(result.object, async () => {
      const result = await executionContext.evaluate(
          {
            expression: functionCall.receiver,
            objectGroup: 'argumentsHint',
            includeCommandLineAPI: true,
            silent: true,
            returnByValue: false,
            generatePreview: false,
            throwOnSideEffect: functionCall.possibleSideEffects,
            timeout: functionCall.possibleSideEffects ? 500 : undefined
          },
          /* userGesture */ false, /* awaitPromise */ false);
      return (result && !result.exceptionDetails) ? result.object : null;
    }, functionCall.functionName);
    executionContext.runtimeModel.releaseObjectGroup('argumentsHint');
    if (!args.length || (args.length === 1 && !args[0].length))
      return null;
    return {args, argumentIndex: functionCall.argumentIndex};
  }

  /**
   * @param {!SDK.RemoteObject} functionObject
   * @param {function():!Promise<?SDK.RemoteObject>} receiverObjGetter
   * @param {string=} parsedFunctionName
   * @return {!Promise<!Array<!Array<string>>>}
   */
  async _argumentsForFunction(functionObject, receiverObjGetter, parsedFunctionName) {
    const description = functionObject.description;
    if (!description.endsWith('{ [native code] }'))
      return [await Formatter.formatterWorkerPool().argumentsList(description)];

    // Check if this is a bound function.
    if (description === 'function () { [native code] }') {
      const properties = await functionObject.getOwnPropertiesPromise(false);
      const internalProperties = properties.internalProperties || [];
      const targetProperty = internalProperties.find(property => property.name === '[[TargetFunction]]');
      const argsProperty = internalProperties.find(property => property.name === '[[BoundArgs]]');
      const thisProperty = internalProperties.find(property => property.name === '[[BoundThis]]');
      if (thisProperty && targetProperty && argsProperty) {
        const originalSignatures =
            await this._argumentsForFunction(targetProperty.value, () => Promise.resolve(thisProperty.value));
        const boundArgsLength = SDK.RemoteObject.arrayLength(argsProperty.value);
        const clippedArgs = [];
        for (const signature of originalSignatures) {
          const restIndex = signature.slice(0, boundArgsLength).findIndex(arg => arg.startsWith('...'));
          if (restIndex !== -1)
            clippedArgs.push(signature.slice(restIndex));
          else
            clippedArgs.push(signature.slice(boundArgsLength));
        }
        return clippedArgs;
      }
    }
    const javaScriptMetadata = await self.runtime.extension(Common.JavaScriptMetadata).instance();

    const name = /^function ([^(]*)\(/.exec(description)[1] || parsedFunctionName;
    if (!name)
      return [];
    const uniqueSignatures = javaScriptMetadata.signaturesForNativeFunction(name);
    if (uniqueSignatures)
      return uniqueSignatures;
    const receiverObj = await receiverObjGetter();
    const className = receiverObj.className;
    if (javaScriptMetadata.signaturesForInstanceMethod(name, className))
      return javaScriptMetadata.signaturesForInstanceMethod(name, className);

    // Check for static methods on a constructor.
    if (receiverObj.type === 'function' && receiverObj.description.endsWith('{ [native code] }')) {
      const receiverName = /^function ([^(]*)\(/.exec(receiverObj.description)[1];
      const staticSignatures = javaScriptMetadata.signaturesForStaticMethod(name, receiverName);
      if (staticSignatures)
        return staticSignatures;
    }


    let protoNames;
    if (receiverObj.type === 'number') {
      protoNames = ['Number', 'Object'];
    } else if (receiverObj.type === 'string') {
      protoNames = ['String', 'Object'];
    } else if (receiverObj.type === 'symbol') {
      protoNames = ['Symbol', 'Object'];
    } else if (receiverObj.type === 'bigint') {
      protoNames = ['BigInt', 'Object'];
    } else if (receiverObj.type === 'boolean') {
      protoNames = ['Boolean', 'Object'];
    } else if (receiverObj.type === 'undefined' || receiverObj.subtype === 'null') {
      protoNames = [];
    } else {
      protoNames = await receiverObj.callFunctionJSONPromise(function() {
        const result = [];
        for (let object = this; object; object = Object.getPrototypeOf(object)) {
          if (typeof object === 'object' && object.constructor && object.constructor.name)
            result[result.length] = object.constructor.name;
        }
        return result;
      });
    }
    for (const proto of protoNames) {
      const instanceSignatures = javaScriptMetadata.signaturesForInstanceMethod(name, proto);
      if (instanceSignatures)
        return instanceSignatures;
    }
    return [];
  }

  /**
   * @param {string} text
   * @param {string} query
   * @return {!Promise<!UI.SuggestBox.Suggestions>}
   */
  async _mapCompletions(text, query) {
    const mapMatch = text.match(/\.\s*(get|set|delete)\s*\(\s*$/);
    const executionContext = UI.context.flavor(SDK.ExecutionContext);
    if (!executionContext || !mapMatch)
      return [];

    const expression = await Formatter.formatterWorkerPool().findLastExpression(text.substring(0, mapMatch.index));
    if (!expression)
      return [];

    const result = await executionContext.evaluate(
        {
          expression: expression.baseExpression,
          objectGroup: 'mapCompletion',
          includeCommandLineAPI: true,
          silent: true,
          returnByValue: false,
          generatePreview: false,
          throwOnSideEffect: expression.possibleSideEffects,
          timeout: expression.possibleSideEffects ? 500 : undefined
        },
        /* userGesture */ false, /* awaitPromise */ false);
    if (result.error || !!result.exceptionDetails || result.object.subtype !== 'map')
      return [];
    const properties = await result.object.getOwnPropertiesPromise(false);
    const internalProperties = properties.internalProperties || [];
    const entriesProperty = internalProperties.find(property => property.name === '[[Entries]]');
    if (!entriesProperty)
      return [];
    const keysObj = await entriesProperty.value.callFunctionJSONPromise(getEntries);
    executionContext.runtimeModel.releaseObjectGroup('mapCompletion');
    return gotKeys(Object.keys(keysObj));

    /**
     * @suppressReceiverCheck
     * @this {!Array<{key:?, value:?}>}
     * @return {!Object}
     */
    function getEntries() {
      const result = {__proto__: null};
      for (let i = 0; i < this.length; i++) {
        if (typeof this[i].key === 'string')
          result[this[i].key] = true;
      }
      return result;
    }

    /**
     * @param {!Array<string>} rawKeys
     * @return {!UI.SuggestBox.Suggestions}
     */
    function gotKeys(rawKeys) {
      const caseSensitivePrefix = [];
      const caseInsensitivePrefix = [];
      const caseSensitiveAnywhere = [];
      const caseInsensitiveAnywhere = [];
      let quoteChar = '"';
      if (query.startsWith('\''))
        quoteChar = '\'';
      let endChar = ')';
      if (mapMatch[0].indexOf('set') !== -1)
        endChar = ', ';

      const sorter = rawKeys.length < 1000 ? String.naturalOrderComparator : undefined;
      const keys = rawKeys.sort(sorter).map(key => quoteChar + key + quoteChar);

      for (const key of keys) {
        if (key.length < query.length)
          continue;
        if (query.length && key.toLowerCase().indexOf(query.toLowerCase()) === -1)
          continue;
        // Substitute actual newlines with newline characters. @see crbug.com/498421
        const title = key.split('\n').join('\\n');
        const text = title + endChar;

        if (key.startsWith(query))
          caseSensitivePrefix.push({text: text, title: title, priority: 4});
        else if (key.toLowerCase().startsWith(query.toLowerCase()))
          caseInsensitivePrefix.push({text: text, title: title, priority: 3});
        else if (key.indexOf(query) !== -1)
          caseSensitiveAnywhere.push({text: text, title: title, priority: 2});
        else
          caseInsensitiveAnywhere.push({text: text, title: title, priority: 1});
      }
      const suggestions =
          caseSensitivePrefix.concat(caseInsensitivePrefix, caseSensitiveAnywhere, caseInsensitiveAnywhere);
      if (suggestions.length)
        suggestions[0].subtitle = Common.UIString('Keys');
      return suggestions;
    }
  }

  /**
   * @param {string} fullText
   * @param {string} query
   * @param {boolean=} force
   * @return {!Promise<!UI.SuggestBox.Suggestions>}
   */
  async _completionsForExpression(fullText, query, force) {
    const executionContext = UI.context.flavor(SDK.ExecutionContext);
    if (!executionContext)
      return [];
    let expression;
    if (fullText.endsWith('.') || fullText.endsWith('['))
      expression = await Formatter.formatterWorkerPool().findLastExpression(fullText.substring(0, fullText.length - 1));
    if (!expression) {
      if (fullText.endsWith('.'))
        return [];
      expression = {baseExpression: '', possibleSideEffects: false};
    }
    const needsNoSideEffects = expression.possibleSideEffects;
    const expressionString = expression.baseExpression;


    const dotNotation = fullText.endsWith('.');
    const bracketNotation = !!expressionString && fullText.endsWith('[');

    // User is entering float value, do not suggest anything.
    if ((expressionString && !isNaN(expressionString)) || (!expressionString && query && !isNaN(query)))
      return [];


    if (!query && !expressionString && !force)
      return [];
    const selectedFrame = executionContext.debuggerModel.selectedCallFrame();
    let completionGroups;
    const TEN_SECONDS = 10000;
    let cache = this._expressionCache.get(expressionString);
    if (cache && cache.date + TEN_SECONDS > Date.now()) {
      completionGroups = await cache.value;
    } else if (!expressionString && selectedFrame) {
      cache = {date: Date.now(), value: completionsOnPause(selectedFrame)};
      this._expressionCache.set(expressionString, cache);
      completionGroups = await cache.value;
    } else {
      const resultPromise = executionContext.evaluate(
          {
            expression: expressionString,
            objectGroup: 'completion',
            includeCommandLineAPI: true,
            silent: true,
            returnByValue: false,
            generatePreview: false,
            throwOnSideEffect: needsNoSideEffects,
            timeout: needsNoSideEffects ? 500 : undefined
          },
          /* userGesture */ false, /* awaitPromise */ false);
      cache = {date: Date.now(), value: resultPromise.then(result => completionsOnGlobal.call(this, result))};
      this._expressionCache.set(expressionString, cache);
      completionGroups = await cache.value;
    }
    return this._receivedPropertyNames(
        completionGroups.slice(0), dotNotation, bracketNotation, expressionString, query);

    /**
     * @this {ObjectUI.JavaScriptAutocomplete}
     * @param {!SDK.RuntimeModel.EvaluationResult} result
     * @return {!Promise<!Array<!ObjectUI.JavaScriptAutocomplete.CompletionGroup>>}
     */
    async function completionsOnGlobal(result) {
      if (result.error || !!result.exceptionDetails || !result.object)
        return [];

      let object = result.object;
      while (object && object.type === 'object' && object.subtype === 'proxy') {
        const properties = await object.getOwnPropertiesPromise(false /* generatePreview */);
        const internalProperties = properties.internalProperties || [];
        const target = internalProperties.find(property => property.name === '[[Target]]');
        object = target ? target.value : null;
      }
      if (!object)
        return [];
      let completions = [];
      if (object.type === 'object' || object.type === 'function') {
        completions =
            await object.callFunctionJSONPromise(getCompletions, [SDK.RemoteObject.toCallArgument(object.subtype)]) ||
            [];
      } else if (
          object.type === 'string' || object.type === 'number' || object.type === 'boolean' ||
          object.type === 'bigint') {
        const evaluateResult = await executionContext.evaluate(
            {
              expression: '(' + getCompletions + ')("' + object.type + '")',
              objectGroup: 'completion',
              includeCommandLineAPI: false,
              silent: true,
              returnByValue: true,
              generatePreview: false
            },
            /* userGesture */ false,
            /* awaitPromise */ false);
        if (evaluateResult.object && !evaluateResult.exceptionDetails)
          completions = evaluateResult.object.value || [];
      }
      executionContext.runtimeModel.releaseObjectGroup('completion');

      if (!expressionString) {
        const globalNames = await executionContext.globalLexicalScopeNames();
        // Merge lexical scope names with first completion group on global object: let a and let b should be in the same group.
        if (completions.length)
          completions[0].items = completions[0].items.concat(globalNames);
        else
          completions.push({items: globalNames.sort(), title: Common.UIString('Lexical scope variables')});
      }

      for (const group of completions) {
        for (let i = 0; i < group.items.length; i++)
          group.items[i] = group.items[i].replace(/\n/g, '\\n');

        group.items.sort(group.items.length < 1000 ? this._itemComparator : undefined);
      }

      return completions;

      /**
       * @param {string=} type
       * @return {!Object}
       * @suppressReceiverCheck
       * @this {Object}
       */
      function getCompletions(type) {
        let object;
        if (type === 'string')
          object = new String('');
        else if (type === 'number')
          object = new Number(0);
        // Object-wrapped BigInts cannot be constructed via `new BigInt`.
        else if (type === 'bigint')
          object = Object(BigInt(0));
        else if (type === 'boolean')
          object = new Boolean(false);
        else
          object = this;

        const result = [];
        try {
          for (let o = object; o; o = Object.getPrototypeOf(o)) {
            if ((type === 'array' || type === 'typedarray') && o === object && o.length > 9999)
              continue;

            const group = {items: [], __proto__: null};
            try {
              if (typeof o === 'object' && o.constructor && o.constructor.name)
                group.title = o.constructor.name;
            } catch (ee) {
              // we could break upon cross origin check.
            }
            result[result.length] = group;
            const names = Object.getOwnPropertyNames(o);
            const isArray = Array.isArray(o);
            for (let i = 0; i < names.length && group.items.length < 10000; ++i) {
              // Skip array elements indexes.
              if (isArray && /^[0-9]/.test(names[i]))
                continue;
              group.items[group.items.length] = names[i];
            }
          }
        } catch (e) {
        }
        return result;
      }
    }

    /**
     * @param {!SDK.DebuggerModel.CallFrame} callFrame
     * @return {!Promise<?Object>}
     */
    async function completionsOnPause(callFrame) {
      const result = [{items: ['this']}];
      const scopeChain = callFrame.scopeChain();
      const groupPromises = [];
      for (const scope of scopeChain) {
        groupPromises.push(scope.object()
                               .getAllPropertiesPromise(false /* accessorPropertiesOnly */, false /* generatePreview */)
                               .then(result => ({properties: result.properties, name: scope.name()})));
      }
      const fullScopes = await Promise.all(groupPromises);
      executionContext.runtimeModel.releaseObjectGroup('completion');
      for (const scope of fullScopes)
        result.push({title: scope.name, items: scope.properties.map(property => property.name).sort()});
      return result;
    }
  }

  /**
   * @param {?Array<!ObjectUI.JavaScriptAutocomplete.CompletionGroup>} propertyGroups
   * @param {boolean} dotNotation
   * @param {boolean} bracketNotation
   * @param {string} expressionString
   * @param {string} query
   * @return {!UI.SuggestBox.Suggestions}
   */
  _receivedPropertyNames(propertyGroups, dotNotation, bracketNotation, expressionString, query) {
    if (!propertyGroups)
      return [];
    const includeCommandLineAPI = (!dotNotation && !bracketNotation);
    if (includeCommandLineAPI) {
      const commandLineAPI = [
        'dir',
        'dirxml',
        'keys',
        'values',
        'profile',
        'profileEnd',
        'monitorEvents',
        'unmonitorEvents',
        'inspect',
        'copy',
        'clear',
        'getEventListeners',
        'debug',
        'undebug',
        'monitor',
        'unmonitor',
        'table',
        'queryObjects',
        '$',
        '$$',
        '$x'
      ];
      propertyGroups.push({items: commandLineAPI});
    }
    return this._completionsForQuery(dotNotation, bracketNotation, expressionString, query, propertyGroups);
  }

  /**
     * @param {boolean} dotNotation
     * @param {boolean} bracketNotation
     * @param {string} expressionString
     * @param {string} query
     * @param {!Array<!ObjectUI.JavaScriptAutocomplete.CompletionGroup>} propertyGroups
     * @return {!UI.SuggestBox.Suggestions}
     */
  _completionsForQuery(dotNotation, bracketNotation, expressionString, query, propertyGroups) {
    const quoteUsed = (bracketNotation && query.startsWith('\'')) ? '\'' : '"';

    if (!expressionString) {
      // See ES2017 spec: https://www.ecma-international.org/ecma-262/8.0/index.html
      const keywords = [
        // Section 11.6.2.1 Reserved keywords.
        'await', 'break', 'case', 'catch', 'class', 'const', 'continue', 'debugger', 'default', 'delete', 'do', 'else',
        'exports', 'extends', 'finally', 'for', 'function', 'if', 'import', 'in', 'instanceof', 'new', 'return',
        'super', 'switch', 'this', 'throw', 'try', 'typeof', 'var', 'void', 'while', 'with', 'yield',

        // Section 11.6.2.1's note mentions words treated as reserved in certain cases.
        'let', 'static',

        // Other keywords not explicitly reserved by spec.
        'async', 'of'
      ];
      propertyGroups.push({title: ls`keywords`, items: keywords.sort()});
    }

    /** @type {!Set<string>} */
    const allProperties = new Set();
    let result = [];
    let lastGroupTitle;
    const regex = /^[a-zA-Z_$\u008F-\uFFFF][a-zA-Z0-9_$\u008F-\uFFFF]*$/;
    const lowerCaseQuery = query.toLowerCase();
    for (const group of propertyGroups) {
      const caseSensitivePrefix = [];
      const caseInsensitivePrefix = [];
      const caseSensitiveAnywhere = [];
      const caseInsensitiveAnywhere = [];

      for (let i = 0; i < group.items.length; i++) {
        let property = group.items[i];
        // Assume that all non-ASCII characters are letters and thus can be used as part of identifier.
        if (!bracketNotation && !regex.test(property))
          continue;

        if (bracketNotation) {
          if (!/^[0-9]+$/.test(property))
            property = quoteUsed + property.escapeCharacters(quoteUsed + '\\') + quoteUsed;
          property += ']';
        }
        if (allProperties.has(property))
          continue;

        if (property.length < query.length)
          continue;
        const lowerCaseProperty = property.toLowerCase();
        if (query.length && lowerCaseProperty.indexOf(lowerCaseQuery) === -1)
          continue;

        allProperties.add(property);
        if (property.startsWith(query))
          caseSensitivePrefix.push({text: property, priority: 4});
        else if (lowerCaseProperty.startsWith(lowerCaseQuery))
          caseInsensitivePrefix.push({text: property, priority: 3});
        else if (property.indexOf(query) !== -1)
          caseSensitiveAnywhere.push({text: property, priority: 2});
        else
          caseInsensitiveAnywhere.push({text: property, priority: 1});
      }
      const structuredGroup =
          caseSensitivePrefix.concat(caseInsensitivePrefix, caseSensitiveAnywhere, caseInsensitiveAnywhere);
      if (structuredGroup.length && group.title !== lastGroupTitle) {
        structuredGroup[0].subtitle = group.title;
        lastGroupTitle = group.title;
      }
      result = result.concat(structuredGroup);
      result.forEach(item => {
        if (item.text.endsWith(']'))
          item.title = item.text.substring(0, item.text.length - 1);
      });
    }
    return result;
  }

  /**
   * @param {string} a
   * @param {string} b
   * @return {number}
   */
  _itemComparator(a, b) {
    const aStartsWithUnderscore = a.startsWith('_');
    const bStartsWithUnderscore = b.startsWith('_');
    if (aStartsWithUnderscore && !bStartsWithUnderscore)
      return 1;
    if (bStartsWithUnderscore && !aStartsWithUnderscore)
      return -1;
    return String.naturalOrderComparator(a, b);
  }
};

/** @typedef {{title:(string|undefined), items:Array<string>}} */
ObjectUI.JavaScriptAutocomplete.CompletionGroup;

ObjectUI.javaScriptAutocomplete = new ObjectUI.JavaScriptAutocomplete();
