var defaults = {
  // If you want to use a different branch of esprima, or any other module
  // that supports a .parse function, pass that module object to
  // recast.parse as options.parser (legacy synonym: options.esprima).
  parser: require("../parsers/esprima"),

  // Number of spaces the pretty-printer should use per tab for
  // indentation. If you do not pass this option explicitly, it will be
  // (quite reliably!) inferred from the original code.
  tabWidth: 4,

  // If you really want the pretty-printer to use tabs instead of spaces,
  // make this option true.
  useTabs: false,

  // The reprinting code leaves leading whitespace untouched unless it has
  // to reindent a line, or you pass false for this option.
  reuseWhitespace: true,

  // Override this option to use a different line terminator, e.g. \r\n.
  lineTerminator: require("os").EOL || "\n",

  // Some of the pretty-printer code (such as that for printing function
  // parameter lists) makes a valiant attempt to prevent really long
  // lines. You can adjust the limit by changing this option; however,
  // there is no guarantee that line length will fit inside this limit.
  wrapColumn: 74, // Aspirational for now.

  // Pass a string as options.sourceFileName to recast.parse to tell the
  // reprinter to keep track of reused code so that it can construct a
  // source map automatically.
  sourceFileName: null,

  // Pass a string as options.sourceMapName to recast.print, and (provided
  // you passed options.sourceFileName earlier) the PrintResult of
  // recast.print will have a .map property for the generated source map.
  sourceMapName: null,

  // If provided, this option will be passed along to the source map
  // generator as a root directory for relative source file paths.
  sourceRoot: null,

  // If you provide a source map that was generated from a previous call
  // to recast.print as options.inputSourceMap, the old source map will be
  // composed with the new source map.
  inputSourceMap: null,

  // If you want esprima to generate .range information (recast only uses
  // .loc internally), pass true for this option.
  range: false,

  // If you want esprima not to throw exceptions when it encounters
  // non-fatal errors, keep this option true.
  tolerant: true,

  // If you want to override the quotes used in string literals, specify
  // either "single", "double", or "auto" here ("auto" will select the one
  // which results in the shorter literal) Otherwise, use double quotes.
  quote: null,

  // Controls the printing of trailing commas in object literals, array
  // expressions and function parameters.
  //
  // This option could either be:
  // * Boolean - enable/disable in all contexts (objects, arrays and function params).
  // * Object - enable/disable per context.
  //
  // Example:
  // trailingComma: {
  //   objects: true,
  //   arrays: true,
  //   parameters: false,
  // }
  trailingComma: false,

  // Controls the printing of spaces inside array brackets.
  // See: http://eslint.org/docs/rules/array-bracket-spacing
  arrayBracketSpacing: false,

  // Controls the printing of spaces inside object literals,
  // destructuring assignments, and import/export specifiers.
  // See: http://eslint.org/docs/rules/object-curly-spacing
  objectCurlySpacing: true,

  // If you want parenthesis to wrap single-argument arrow function
  // parameter lists, pass true for this option.
  arrowParensAlways: false,

  // There are 2 supported syntaxes (`,` and `;`) in Flow Object Types;
  // The use of commas is in line with the more popular style and matches
  // how objects are defined in JS, making it a bit more natural to write.
  flowObjectCommas: true,

  // Whether to return an array of .tokens on the root AST node.
  tokens: true

}, hasOwn = defaults.hasOwnProperty;

// Copy options and fill in default values.
exports.normalize = function(options) {
  options = options || defaults;

  function get(key) {
    return hasOwn.call(options, key)
      ? options[key]
      : defaults[key];
  }

  return {
    tabWidth: +get("tabWidth"),
    useTabs: !!get("useTabs"),
    reuseWhitespace: !!get("reuseWhitespace"),
    lineTerminator: get("lineTerminator"),
    wrapColumn: Math.max(get("wrapColumn"), 0),
    sourceFileName: get("sourceFileName"),
    sourceMapName: get("sourceMapName"),
    sourceRoot: get("sourceRoot"),
    inputSourceMap: get("inputSourceMap"),
    parser: get("esprima") || get("parser"),
    range: get("range"),
    tolerant: get("tolerant"),
    quote: get("quote"),
    trailingComma: get("trailingComma"),
    arrayBracketSpacing: get("arrayBracketSpacing"),
    objectCurlySpacing: get("objectCurlySpacing"),
    arrowParensAlways: get("arrowParensAlways"),
    flowObjectCommas: get("flowObjectCommas"),
    tokens: !!get("tokens")
  };
};
