// Copyright (c) 2017, 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:async';
import 'dart:convert';
import 'dart:typed_data';

import 'package:meta/meta.dart';
import 'package:file/file.dart';
import 'package:file/src/io.dart' as io;

import 'recording_file_system.dart';
import 'recording_file_system_entity.dart';
import 'recording_io_sink.dart';
import 'recording_random_access_file.dart';
import 'result_reference.dart';

/// Callback responsible for synchronously writing result [data] to the
/// specified [file].
///
/// See also:
///   - [_BlobReference]
///   - [_BlobStreamReference]
typedef void _BlobDataSyncWriter<T>(File file, T data);

/// Callback responsible for asynchronously writing result [data] to the
/// specified [file].
///
/// See also:
///   - [_BlobFutureReference]
typedef Future<Null> _BlobDataAsyncWriter<T>(File file, T data);

/// [File] implementation that records all invocation activity to its file
/// system's recording.
class RecordingFile extends RecordingFileSystemEntity<File> implements File {
  /// Creates a new `RecordingFile`.
  RecordingFile(RecordingFileSystem fileSystem, io.File delegate)
      : super(fileSystem, delegate) {
    methods.addAll(<Symbol, Function>{
      #create: _create,
      #createSync: delegate.createSync,
      #copy: _copy,
      #copySync: _copySync,
      #length: delegate.length,
      #lengthSync: delegate.lengthSync,
      #lastAccessed: delegate.lastAccessed,
      #lastAccessedSync: delegate.lastAccessedSync,
      #setLastAccessed: delegate.setLastAccessed,
      #setLastAccessedSync: delegate.setLastAccessedSync,
      #lastModified: delegate.lastModified,
      #lastModifiedSync: delegate.lastModifiedSync,
      #setLastModified: delegate.setLastModified,
      #setLastModifiedSync: delegate.setLastModifiedSync,
      #open: _open,
      #openSync: _openSync,
      #openRead: _openRead,
      #openWrite: _openWrite,
      #readAsBytes: _readAsBytes,
      #readAsBytesSync: _readAsBytesSync,
      #readAsString: _readAsString,
      #readAsStringSync: _readAsStringSync,
      #readAsLines: _readAsLines,
      #readAsLinesSync: _readAsLinesSync,
      #writeAsBytes: _writeAsBytes,
      #writeAsBytesSync: delegate.writeAsBytesSync,
      #writeAsString: _writeAsString,
      #writeAsStringSync: delegate.writeAsStringSync,
    });
  }

  @override
  File wrap(File delegate) => super.wrap(delegate) ?? wrapFile(delegate);

  File _newRecordingFile() => recording.newFile(delegate.basename);

  RandomAccessFile _wrapRandomAccessFile(RandomAccessFile delegate) =>
      new RecordingRandomAccessFile(fileSystem, delegate);

  Future<File> _create({bool recursive: false}) =>
      delegate.create(recursive: recursive).then(wrap);

  Future<File> _copy(String newPath) => delegate.copy(newPath).then(wrap);

  File _copySync(String newPath) => wrap(delegate.copySync(newPath));

  Future<RandomAccessFile> _open({FileMode mode: FileMode.read}) =>
      delegate.open(mode: mode).then(_wrapRandomAccessFile);

  RandomAccessFile _openSync({FileMode mode: FileMode.read}) =>
      _wrapRandomAccessFile(delegate.openSync(mode: mode));

  StreamReference<Uint8List> _openRead([int start, int end]) {
    return new _BlobStreamReference<Uint8List>(
      file: _newRecordingFile(),
      stream: delegate.openRead(start, end),
      writer: (File file, Uint8List bytes) {
        file.writeAsBytesSync(bytes, mode: FileMode.append, flush: true);
      },
    );
  }

  IOSink _openWrite({FileMode mode: FileMode.write, Encoding encoding: utf8}) {
    return new RecordingIOSink(
      fileSystem,
      delegate.openWrite(mode: mode, encoding: encoding),
    );
  }

  FutureReference<Uint8List> _readAsBytes() {
    return new _BlobFutureReference<Uint8List>(
      file: _newRecordingFile(),
      future: delegate.readAsBytes(),
      writer: (File file, Uint8List bytes) async {
        await file.writeAsBytes(bytes, flush: true);
      },
    );
  }

  ResultReference<Uint8List> _readAsBytesSync() {
    return new _BlobReference<Uint8List>(
      file: _newRecordingFile(),
      value: delegate.readAsBytesSync(),
      writer: (File file, Uint8List bytes) {
        file.writeAsBytesSync(bytes, flush: true);
      },
    );
  }

  FutureReference<String> _readAsString({Encoding encoding: utf8}) {
    return new _BlobFutureReference<String>(
      file: _newRecordingFile(),
      future: delegate.readAsString(encoding: encoding),
      writer: (File file, String content) async {
        await file.writeAsString(content, flush: true);
      },
    );
  }

  ResultReference<String> _readAsStringSync({Encoding encoding: utf8}) {
    return new _BlobReference<String>(
      file: _newRecordingFile(),
      value: delegate.readAsStringSync(encoding: encoding),
      writer: (File file, String content) {
        file.writeAsStringSync(content, flush: true);
      },
    );
  }

  FutureReference<List<String>> _readAsLines({Encoding encoding: utf8}) {
    return new _BlobFutureReference<List<String>>(
      file: _newRecordingFile(),
      future: delegate.readAsLines(encoding: encoding),
      writer: (File file, List<String> lines) async {
        await file.writeAsString(lines.join('\n'), flush: true);
      },
    );
  }

  ResultReference<List<String>> _readAsLinesSync({Encoding encoding: utf8}) {
    return new _BlobReference<List<String>>(
      file: _newRecordingFile(),
      value: delegate.readAsLinesSync(encoding: encoding),
      writer: (File file, List<String> lines) {
        file.writeAsStringSync(lines.join('\n'), flush: true);
      },
    );
  }

  Future<File> _writeAsBytes(
    List<int> bytes, {
    FileMode mode: FileMode.write,
    bool flush: false,
  }) =>
      delegate.writeAsBytes(bytes, mode: mode, flush: flush).then(wrap);

  Future<File> _writeAsString(
    String contents, {
    FileMode mode: FileMode.write,
    Encoding encoding: utf8,
    bool flush: false,
  }) =>
      delegate
          .writeAsString(contents, mode: mode, encoding: encoding, flush: flush)
          .then(wrap);
}

/// A [ResultReference] that serializes its value data to a separate file.
class _BlobReference<T> extends ResultReference<T> {
  final File _file;
  final T _value;
  final _BlobDataSyncWriter<T> _writer;

  _BlobReference({
    @required File file,
    @required T value,
    @required _BlobDataSyncWriter<T> writer,
  })  : _file = file,
        _value = value,
        _writer = writer;

  @override
  T get value {
    _writer(_file, _value);
    return _value;
  }

  @override
  T get recordedValue => _value;

  @override
  String get serializedValue => '!${_file.basename}';
}

/// A [FutureReference] that serializes its value data to a separate file.
class _BlobFutureReference<T> extends FutureReference<T> {
  final File _file;
  final _BlobDataAsyncWriter<T> _writer;

  _BlobFutureReference({
    @required File file,
    @required Future<T> future,
    @required _BlobDataAsyncWriter<T> writer,
  })  : _file = file,
        _writer = writer,
        super(future);

  @override
  Future<T> get value {
    return super.value.then((T value) async {
      await _writer(_file, value);
      return value;
    });
  }

  @override
  String get serializedValue => '!${_file.basename}';
}

/// A [StreamReference] that serializes its value data to a separate file.
class _BlobStreamReference<T> extends StreamReference<T> {
  final File _file;
  final _BlobDataSyncWriter<T> _writer;

  _BlobStreamReference({
    @required File file,
    @required Stream<T> stream,
    @required _BlobDataSyncWriter<T> writer,
  })  : _file = file,
        _writer = writer,
        super(stream);

  @override
  void onData(T event) {
    _writer(_file, event);
  }

  @override
  String get serializedValue => '!${_file.basename}';
}
