#!/usr/bin/env dart

// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:convert';
import 'dart:io';

import 'package:args/args.dart';
import 'package:path/path.dart' as path;

import 'package:analyzer/src/services/formatter_impl.dart';


const BINARY_NAME = 'dartfmt';
final dartFileRegExp = new RegExp(r'^[^.].*\.dart$', caseSensitive: false);
final argParser = _initArgParser();
final defaultSelection = new Selection(-1, -1);

var formatterSettings;

CodeKind kind;
bool machineFormat;
bool overwriteFileContents;
Selection selection;
final List<String> paths = [];


const HELP_FLAG = 'help';
const KIND_FLAG = 'kind';
const MACHINE_FLAG = 'machine';
const WRITE_FLAG = 'write';
const SELECTION_FLAG = 'selection';
const TRANSFORM_FLAG = 'transform';
const MAX_LINE_FLAG = 'max_line_length';


const FOLLOW_LINKS = false;


main(args) {
  var options = argParser.parse(args);
  if (options['help']) {
    _printUsage();
    return;
  }

  _readOptions(options);

  if (options.rest.isEmpty) {
    _formatStdin(kind);
  } else {
    paths.addAll(options.rest);
    _formatPaths(paths);
  }
}

_readOptions(options) {
  kind = _parseKind(options[KIND_FLAG]);
  machineFormat = options[MACHINE_FLAG];
  overwriteFileContents = options[WRITE_FLAG];
  selection = _parseSelection(options[SELECTION_FLAG]);
  formatterSettings =
      new FormatterOptions(codeTransforms: options[TRANSFORM_FLAG],
          pageWidth: _parseLineLength(options[MAX_LINE_FLAG]));
}

CodeKind _parseKind(kindOption) {
  switch(kindOption) {
    case 'stmt' :
      return CodeKind.STATEMENT;
    default:
      return CodeKind.COMPILATION_UNIT;
  }
}

int _parseLineLength(String lengthOption) {
  var length = _toInt(lengthOption);
  if (length == null) {
    var val = lengthOption.toUpperCase();
    if (val == 'INF' || val == 'INFINITY') {
      length = -1;
    } else {
      throw new FormatterException('Line length is specified as an Integer or '
          'the value "Inf".');
    }
  }
  return length;
}


Selection _parseSelection(selectionOption) {
  if (selectionOption != null) {
    var units = selectionOption.split(',');
    if (units.length == 2) {
      var offset = _toInt(units[0]);
      var length = _toInt(units[1]);
      if (offset != null && length != null) {
        return new Selection(offset, length);
      }
    }
    throw new FormatterException('Selections are specified as integer pairs '
                                 '(e.g., "(offset, length)".');
  }
}

int _toInt(str) => int.parse(str, onError: (_) => null);

_formatPaths(paths) {
  paths.forEach((path) {
    if (FileSystemEntity.isDirectorySync(path)) {
      _formatDirectory(new Directory(path));
    } else {
      _formatFile(new File(path));
    }
  });
}

_formatResource(resource) {
  if (resource is Directory) {
    _formatDirectory(resource);
  } else if (resource is File) {
    _formatFile(resource);
  }
}

_formatDirectory(dir) => dir.listSync(followLinks: FOLLOW_LINKS)
    .forEach((resource) => _formatResource(resource));

_formatFile(file) {
  if (_isDartFile(file)) {
    if (_isPatchFile(file) && !paths.contains(file.path)) {
      _log('Skipping patch file "${file.path}"');
      return;
    }
    try {
      var buffer = new StringBuffer();
      var rawSource = file.readAsStringSync();
      var formatted = _format(rawSource, CodeKind.COMPILATION_UNIT);
      if (overwriteFileContents) {
        // Only touch files files whose contents will be changed
        if (rawSource != formatted) {
          file.writeAsStringSync(formatted);
        }
      } else {
        print(formatted);
      }
    } catch (e) {
      _log('Unable to format "${file.path}": $e');
    }
  }
}

_isPatchFile(file) => file.path.endsWith('_patch.dart');

_isDartFile(file) => dartFileRegExp.hasMatch(path.basename(file.path));

_formatStdin(kind) {
  var input = new StringBuffer();
  stdin.transform(new Utf8Decoder())
      .listen((data) => input.write(data),
        onError: (error) => _log('Error reading from stdin'),
        onDone: () => print(_format(input.toString(), kind)));
}

/// Initialize the arg parser instance.
ArgParser _initArgParser() {
  // NOTE: these flags are placeholders only!
  var parser = new ArgParser();
  parser.addFlag(WRITE_FLAG, abbr: 'w', negatable: false,
      help: 'Write reformatted sources to files (overwriting contents).  '
            'Do not print reformatted sources to standard output.');
  parser.addFlag(TRANSFORM_FLAG, abbr: 't', negatable: false,
      help: 'Perform code transformations.');
  parser.addOption(MAX_LINE_FLAG, abbr: 'l', defaultsTo: '80',
      help: 'Wrap lines longer than this length. '
            'To never wrap, specify "Infinity" or "Inf" for short.');
  parser.addOption(KIND_FLAG, abbr: 'k', defaultsTo: 'cu',
      help: 'Specify source snippet kind ("stmt" or "cu") '
            '--- [PROVISIONAL API].', hide: true);
  parser.addOption(SELECTION_FLAG, abbr: 's',
      help: 'Specify selection information as an offset,length pair '
            '(e.g., -s "0,4").', hide: true);
  parser.addFlag(MACHINE_FLAG, abbr: 'm', negatable: false,
      help: 'Produce output in a format suitable for parsing.');
  parser.addFlag(HELP_FLAG, abbr: 'h', negatable: false,
      help: 'Print this usage information.');
  return parser;
}


/// Displays usage information.
_printUsage() {
  var buffer = new StringBuffer();
  buffer..write('$BINARY_NAME formats Dart programs.')
        ..write('\n\n')
        ..write('Without an explicit path, $BINARY_NAME processes the standard '
                'input.  Given a file, it operates on that file; given a '
                'directory, it operates on all .dart files in that directory, '
                'recursively. (Files starting with a period are ignored.) By '
                'default, $BINARY_NAME prints the reformatted sources to '
                'standard output.')
        ..write('\n\n')
        ..write('Usage: $BINARY_NAME [flags] [path...]\n\n')
        ..write('Supported flags are:\n')
        ..write('${argParser.getUsage()}\n\n');
  _log(buffer.toString());
}

/// Format this [src], treating it as the given snippet [kind].
String _format(src, kind) {
  var formatResult = new CodeFormatter(formatterSettings).format(
      kind, src, selection: selection);
  if (machineFormat) {
    if (formatResult.selection == null) {
      formatResult.selection = defaultSelection;
    }
    return _toJson(formatResult);
  }
  return formatResult.source;
}

_toJson(formatResult) =>
    // Actual JSON format TBD
    JSON.encode({'source': formatResult.source,
                 'selection': {
                     'offset': formatResult.selection.offset,
                     'length': formatResult.selection.length
                  }
    });

/// Log the given [msg].
_log(String msg) {
  //TODO(pquitslund): add proper log support
  print(msg);
}