// 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.
// Testing file input stream, VM-only, standalone test.
//
// OtherResources=readuntil_test.dat
// OtherResources=readline_test1.dat
// OtherResources=readline_test2.dat

import "dart:convert";
import "dart:io";

import "package:async_helper/async_helper.dart";
import "package:expect/expect.dart";

String getFilename(String path) {
  return Platform.script.resolve(path).toFilePath();
}

void testStringLineSplitter() {
  String fileName = getFilename("readuntil_test.dat");
  // File contains "Hello Dart\nwassup!\n"
  File file = new File(fileName);
  int linesRead = 0;
  var lineStream = file
      .openRead()
      .cast<List<int>>()
      .transform(utf8.decoder)
      .transform(new LineSplitter());
  lineStream.listen((line) {
    linesRead++;
    if (linesRead == 1) {
      Expect.equals("Hello Dart", line);
    } else if (linesRead == 2) {
      Expect.equals("wassup!", line);
    } else {
      Expect.fail("More or less than 2 lines read ($linesRead lines read).");
    }
  });
}

void testOpenStreamAsync() {
  asyncStart();
  String fileName = getFilename("readuntil_test.dat");
  // File contains "Hello Dart\nwassup!\n"
  var expected = "Hello Dart\nwassup!\n".codeUnits;
  var byteCount = 0;
  (new File(fileName)).openRead().listen((d) => byteCount += d.length,
      onDone: () {
    Expect.equals(expected.length, byteCount);
    asyncEnd();
  });
}

// Create a file that is big enough that a file stream will
// read it in multiple chunks.
int writeLongFileSync(File file) {
  file.createSync();
  StringBuffer buffer = new StringBuffer();
  for (var i = 0; i < 50000; i++) {
    buffer.write("Hello, world");
  }
  file.writeAsStringSync(buffer.toString());
  var length = file.lengthSync();
  Expect.equals(buffer.length, length);
  return length;
}

void testInputStreamTruncate() {
  asyncStart();
  var temp = Directory.systemTemp.createTempSync('file_input_stream_test');
  var file = new File('${temp.path}/input_stream_truncate.txt');
  var originalLength = writeLongFileSync(file);
  // Start streaming the file. Pause after first chunk. Truncate
  // underlying file and check that the streaming stops with or
  // without getting all data.
  var streamedBytes = 0;
  var subscription;
  subscription = file.openRead().listen((d) {
    if (streamedBytes == 0) {
      subscription.pause();
      // Truncate the file by opening it for writing.
      file.open(mode: FileMode.write).then((opened) {
        opened.close().then((_) {
          Expect.equals(0, file.lengthSync());
          subscription.resume();
        });
      });
    }
    streamedBytes += d.length;
  }, onDone: () {
    Expect.isTrue(streamedBytes > 0 && streamedBytes <= originalLength);
    temp.delete(recursive: true).then((_) => asyncEnd());
  }, onError: (e) {
    Expect.fail("Unexpected error");
  });
}

void testInputStreamDelete() {
  asyncStart();
  var temp = Directory.systemTemp.createTempSync('file_input_stream_test');
  var file = new File('${temp.path}/input_stream_delete.txt');
  var originalLength = writeLongFileSync(file);
  // Start streaming the file. Pause after first chunk. Truncate
  // underlying file and check that the streaming stops with or
  // without getting all data.
  var streamedBytes = 0;
  var subscription;
  subscription = file.openRead().listen((d) {
    if (streamedBytes == 0) {
      subscription.pause();
      // Delete the underlying file by opening it for writing.
      file.delete().then((deleted) {
        Expect.isFalse(deleted.existsSync());
        subscription.resume();
      }).catchError((e) {
        // On Windows, you cannot delete a file that is open
        // somewhere else. The stream has this file open
        // and therefore we get an error on deletion on Windows.
        Expect.equals('windows', Platform.operatingSystem);
        subscription.resume();
      });
    }
    streamedBytes += d.length;
  }, onDone: () {
    Expect.equals(originalLength, streamedBytes);
    temp.delete(recursive: true).then((_) => asyncEnd());
  }, onError: (e) {
    Expect.fail("Unexpected error");
  });
}

void testInputStreamAppend() {
  asyncStart();
  var temp = Directory.systemTemp.createTempSync('file_input_stream_test');
  var file = new File('${temp.path}/input_stream_append.txt');
  var originalLength = writeLongFileSync(file);
  // Start streaming the file. Pause after first chunk. Append to
  // underlying file and check that the stream gets all the data.
  var streamedBytes = 0;
  var subscription;
  subscription = file.openRead().listen((d) {
    if (streamedBytes == 0) {
      subscription.pause();
      // Double the length of the underlying file.
      file.readAsBytes().then((bytes) {
        file.writeAsBytes(bytes, mode: FileMode.append).then((_) {
          Expect.equals(2 * originalLength, file.lengthSync());
          subscription.resume();
        });
      });
    }
    streamedBytes += d.length;
  }, onDone: () {
    Expect.equals(2 * originalLength, streamedBytes);
    temp.delete(recursive: true).then((_) => asyncEnd());
  }, onError: (e) {
    Expect.fail("Unexpected error");
  });
}

void testInputStreamOffset() {
  void test(int? start, int? end, int expectedBytes) {
    asyncStart();
    var temp = Directory.systemTemp.createTempSync('file_input_stream_test');
    var file = new File('${temp.path}/input_stream_offset.txt');
    var originalLength = writeLongFileSync(file);
    var streamedBytes = 0;
    if (expectedBytes < 0) expectedBytes = originalLength + expectedBytes;
    file.openRead(start, end).listen((d) {
      streamedBytes += d.length;
    }, onDone: () {
      Expect.equals(expectedBytes, streamedBytes);
      temp.delete(recursive: true).then((_) => asyncEnd());
    }, onError: (e) {
      Expect.fail("Unexpected error");
    });
  }

  test(10, 20, 10);
  test(10, 11, 1);
  test(10, 10, 0);
  test(100000000, null, 0);
  test(null, 0, 0);
  test(null, 1, 1);
  test(1, null, -1);
  test(20, null, -20);
}

void testInputStreamBadOffset() {
  void test(int? start, int? end) {
    asyncStart();
    var temp = Directory.systemTemp.createTempSync('file_input_stream_test');
    var file = new File('${temp.path}/input_stream_bad_offset.txt');
    var originalLength = writeLongFileSync(file);
    var streamedBytes = 0;
    bool error = false;
    file.openRead(start, end).listen((d) {
      streamedBytes += d.length;
    }, onDone: () {
      Expect.isTrue(error);
      temp.deleteSync(recursive: true);
      asyncEnd();
    }, onError: (e) {
      error = true;
    });
  }

  test(-1, null);
  test(100, 99);
  test(null, -1);
}

void testStringLineSplitterEnding(String name, int length) {
  String fileName = getFilename(name);
  // File contains 10 lines.
  File file = new File(fileName);
  Expect.equals(length, file.lengthSync());
  var lineStream = file
      .openRead()
      .cast<List<int>>()
      .transform(utf8.decoder)
      .transform(new LineSplitter());
  int lineCount = 0;
  lineStream.listen((line) {
    lineCount++;
    Expect.isTrue(lineCount <= 10);
    if (line[0] != "#") {
      Expect.equals("Line $lineCount", line);
    }
  }, onDone: () {
    Expect.equals(10, lineCount);
  });
}

main() {
  testStringLineSplitter();
  testOpenStreamAsync();
  testInputStreamTruncate();
  testInputStreamDelete();
  testInputStreamAppend();
  testInputStreamOffset();
  testInputStreamBadOffset();
  // Check the length of these files as both are text files where one
  // is without a terminating line separator which can easily be added
  // back if accidentally opened in a text editor.
  testStringLineSplitterEnding("readline_test1.dat", 111);
  testStringLineSplitterEnding("readline_test2.dat", 114);
}
