text: /* @flow */
  
  import { InputTypeComposer } from 'graphql-compose';
  import { getQueryITC, prepareQueryInResolve } from '../Query';
  import { getTypeName, type CommonOpts, desc } from '../../../utils';
  
  export function getFunctionScoreITC<TContext>(
    opts: CommonOpts<TContext>
  ): InputTypeComposer<TContext> {
    const name = getTypeName('QueryFunctionScore', opts);
    const description = desc(
      `
      The function_score allows you to modify the score of documents that
      are retrieved by a query. This can be useful if, for example,
      a score function is computationally expensive and it is sufficient
      to compute the score on a filtered set of documents.
      [Documentation](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html)
    `
    );
  
    const RandomScoreType = opts.schemaComposer.createInputTC({
      name: getTypeName('QueryFunctionScoreRandom', opts),
      fields: {
        seed: 'Float',
      },
    });
  
    return opts.getOrCreateITC(name, () => ({
      name,
      description,
      fields: {
        query: (): InputTypeComposer<TContext> => getQueryITC(opts),
        boost: 'String',
        boost_mode: {
          type: 'String',
          description: 'Can be: `multiply`, `replace`, `sum`, `avg`, `max`, `min`.',
        },
        random_score: RandomScoreType,
        functions: [
          opts.schemaComposer.createInputTC({
            name: getTypeName('QueryFunctionScoreFunction', opts),
            fields: {
              filter: (): InputTypeComposer<TContext> => getQueryITC(opts),
              random_score: RandomScoreType,
              weight: 'Float',
              script_score: 'JSON',
              field_value_factor: 'JSON',
              gauss: 'JSON',
              linear: 'JSON',
              exp: 'JSON',
            },
          }),
        ],
        max_boost: 'Float',
        score_mode: {
          type: 'String',
          description: 'Can be: `multiply`, `sum`, `avg`, `first`, `max`, `min`.',
        },
        min_score: 'Float',
      },
    }));
  }
  
  /* eslint-disable no-param-reassign, camelcase */
  export function prepareFunctionScoreInResolve(
    function_score: any,
    fieldMap: mixed
  ): { [argName: string]: any } {
    if (function_score.query) {
      function_score.query = prepareQueryInResolve(function_score.query, fieldMap);
    }
  
    if (Array.isArray(function_score.functions)) {
      function_score.functions = function_score.functions.map((func) => {
        if (func.filter) {
          func.filter = prepareQueryInResolve(func.filter, fieldMap);
        }
        return func;
      });
    }
  
    return function_score;
  }
  