// Copyright (c) 2012, 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.

library parser;

import 'dart:io';
import 'dart:typed_data';
import 'dart:collection';
import 'dart:utf';

import '../elements/elements.dart';
import '../scanner/scanner_implementation.dart';
import '../scanner/scannerlib.dart';
import '../tree/tree.dart';
import '../util/characters.dart';
import '../source_file.dart';
import '../ssa/ssa.dart';

import '../../compiler.dart' as api;

part '../diagnostic_listener.dart';
part '../scanner/byte_array_scanner.dart';
part '../scanner/byte_strings.dart';

int charCount = 0;
Stopwatch stopwatch;

void main() {
  toolMain(new Options().arguments);
}

void toolMain(List<String> arguments) {
  filesWithCrashes = [];
  stopwatch = new Stopwatch();
  MyOptions options = new MyOptions();

  void printStats() {
    int kb = (charCount / 1024).round();
    String stats =
        '$classCount classes (${kb}Kb) in ${stopwatch.elapsedMilliseconds}ms';
    if (errorCount != 0) {
      stats = '$stats with $errorCount errors';
    }
    if (options.diet) {
      print('Diet parsed $stats.');
    } else {
      print('Parsed $stats.');
    }
    if (filesWithCrashes.length != 0) {
      print('The following ${filesWithCrashes.length} files caused a crash:');
      for (String file in filesWithCrashes) {
        print(file);
      }
    }
  }

  for (String argument in arguments) {
    if (argument == "--diet") {
      options.diet = true;
      continue;
    }
    if (argument == "--throw") {
      options.throwOnError = true;
      continue;
    }
    if (argument == "--scan-only") {
      options.scanOnly = true;
      continue;
    }
    if (argument == "--read-only") {
      options.readOnly = true;
      continue;
    }
    if (argument == "--ast") {
      options.buildAst = true;
      continue;
    }
    if (argument == "-") {
      parseFilesFrom(stdin, options, printStats);
      return;
    }
    stopwatch.start();
    parseFile(argument, options);
    stopwatch.stop();
  }

  printStats();
}

void parseFile(String filename, MyOptions options) {
  List<int> bytes = read(filename);
  charCount += bytes.length;
  if (options.readOnly) return;
  MySourceFile file = new MySourceFile(filename, bytes);
  final Listener listener = options.buildAst
      ? new MyNodeListener(file, options)
      : new MyListener(file);
  final Parser parser = options.diet
      ? new PartialParser(listener)
      : new Parser(listener);
  try {
    Token token = scan(file);
    if (!options.scanOnly) parser.parseUnit(token);
  } on ParserError catch (ex) {
    if (options.throwOnError) {
      throw;
    } else {
      print(ex);
    }
  } catch (ex) {
    print('Error in file: $filename');
    throw;
  }
  if (options.buildAst) {
    MyNodeListener l = listener;
    if (!l.nodes.isEmpty) {
      String message = 'Stack not empty after parsing';
      print(formatError(message, l.nodes.head.getBeginToken(),
                        l.nodes.head.getEndToken(), file));
      throw message;
    }
  }
}

Token scan(MySourceFile source) {
  Scanner scanner = new ByteArrayScanner(source.rawText);
  return scanner.tokenize();
}

var filesWithCrashes;

void parseFilesFrom(InputStream input, MyOptions options, Function whenDone) {
  void readLine(String line) {
    stopwatch.start();
    try {
      parseFile(line, options);
    } catch (ex, trace) {
      filesWithCrashes.add(line);
      print(ex);
      print(trace);
    }
    stopwatch.stop();
  }
  forEachLine(input, readLine, whenDone);
}

void forEachLine(InputStream input,
                 void lineHandler(String line),
                 void closeHandler()) {
  StringInputStream stringStream = new StringInputStream(input);
  stringStream.onLine = () {
    String line;
    while ((line = stringStream.readLine()) != null) {
      lineHandler(line);
    }
  };
  stringStream.onClosed = closeHandler;
}

List<int> read(String filename) {
  RandomAccessFile file = new File(filename).openSync();
  bool threw = true;
  try {
    int size = file.lengthSync();
    List<int> bytes = new Uint8List(size + 1);
    file.readIntoSync(bytes, 0, size);
    bytes[size] = $EOF;
    threw = false;
    return bytes;
  } finally {
    try {
      file.closeSync();
    } catch (ex) {
      if (!threw) throw;
    }
  }
}

int classCount = 0;
int errorCount = 0;

class MyListener extends Listener {
  final SourceFile file;

  MyListener(this.file);

  void beginClassDeclaration(Token token) {
    classCount++;
  }

  void beginInterface(Token token) {
    classCount++;
  }

  void error(String message, Token token) {
    throw new ParserError(formatError(message, token, token, file));
  }
}

String formatError(String message, Token beginToken, Token endToken,
                   SourceFile file) {
  ++errorCount;
  if (beginToken == null) return '${file.filename}: $message';
  String tokenString = endToken.toString();
  int begin = beginToken.charOffset;
  int end = endToken.charOffset + tokenString.length;
  return file.getLocationMessage(message, begin, end, true, (x) => x);
}

class MyNodeListener extends NodeListener {
  MyNodeListener(SourceFile file, MyOptions options)
    : super(new MyCanceller(file, options), null);

  void beginClassDeclaration(Token token) {
    classCount++;
  }

  void beginInterface(Token token) {
    classCount++;
  }

  void endClassDeclaration(int interfacesCount, Token beginToken,
                           Token extendsKeyword, Token implementsKeyword,
                           Token endToken) {
    super.endClassDeclaration(interfacesCount, beginToken,
                              extendsKeyword, implementsKeyword,
                              endToken);
    ClassNode node = popNode(); // Discard ClassNode and assert the type.
  }

  void endTopLevelFields(int count, Token beginToken, Token endToken) {
    super.endTopLevelFields(count, beginToken, endToken);
    VariableDefinitions node = popNode(); // Discard node and assert the type.
  }

  void endFunctionTypeAlias(Token typedefKeyword, Token endToken) {
    super.endFunctionTypeAlias(typedefKeyword, endToken);
    Typedef node = popNode(); // Discard Typedef and assert type type.
  }

  void endLibraryTag(bool hasPrefix, Token beginToken, Token endToken) {
    super.endLibraryTag(hasPrefix, beginToken, endToken);
    ScriptTag node = popNode(); // Discard ScriptTag and assert type type.
  }

  void log(message) {
    print(message);
  }
}

class MyCanceller implements DiagnosticListener {
  final SourceFile file;
  final MyOptions options;

  MyCanceller(this.file, this.options);

  void log(String message) {}

  void cancel(String reason, {node, token, instruction, element}) {
    Token beginToken;
    Token endToken;
    if (token != null) {
      beginToken = token;
      endToken = token;
    } else if (node != null) {
      beginToken = node.getBeginToken();
      endToken = node.getEndToken();
    }
    String message = formatError(reason, beginToken, endToken, file);
    if (options.throwOnError) throw new ParserError(message);
    print(message);
  }
}

class MyOptions {
  bool diet = false;
  bool throwOnError = false;
  bool scanOnly = false;
  bool readOnly = false;
  bool buildAst = false;
}

class MySourceFile extends SourceFile {
  final rawText;
  var stringText;

  MySourceFile(filename, this.rawText) : super(filename, null);

  String get text {
    if (rawText is String) {
      return rawText;
    } else {
      if (stringText == null) {
        stringText = new String.fromCharCodes(rawText);
        if (stringText.endsWith('\u0000')) {
          // Strip trailing NUL used by ByteArrayScanner to signal EOF.
          stringText = stringText.substring(0, stringText.length - 1);
        }
      }
      return stringText;
    }
  }

  set text(String newText) {
    throw "not supported";
  }
}

class Mock {
  const Mock();
  bool get useColors => true;
  internalError(message) { throw message.toString(); }
}
