// 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:math' as math show min;
import 'dart:typed_data';

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

import 'common.dart';
import 'memory_file_system_entity.dart';
import 'memory_random_access_file.dart';
import 'node.dart';
import 'utils.dart' as utils;

/// Internal implementation of [File].
class MemoryFile extends MemoryFileSystemEntity implements File {
  /// Instantiates a new [MemoryFile].
  const MemoryFile(NodeBasedFileSystem fileSystem, String path)
      : super(fileSystem, path);

  FileNode get _resolvedBackingOrCreate {
    Node node = backingOrNull;
    if (node == null) {
      node = _doCreate();
    } else {
      node = utils.isLink(node) ? utils.resolveLinks(node, () => path) : node;
      utils.checkType(expectedType, node.type, () => path);
    }
    return node;
  }

  @override
  io.FileSystemEntityType get expectedType => io.FileSystemEntityType.file;

  @override
  bool existsSync() => backingOrNull?.stat?.type == expectedType;

  @override
  Future<File> create({bool recursive = false}) async {
    createSync(recursive: recursive);
    return this;
  }

  @override
  void createSync({bool recursive = false}) {
    _doCreate(recursive: recursive);
  }

  Node _doCreate({bool recursive = false}) {
    Node node = internalCreateSync(
      followTailLink: true,
      createChild: (DirectoryNode parent, bool isFinalSegment) {
        if (isFinalSegment) {
          return FileNode(parent);
        } else if (recursive) {
          return DirectoryNode(parent);
        }
        return null;
      },
    );
    if (node.type != expectedType) {
      // There was an existing non-file entity at this object's path
      assert(node.type == FileSystemEntityType.directory);
      throw common.isADirectory(path);
    }
    return node;
  }

  @override
  Future<File> rename(String newPath) async => renameSync(newPath);

  @override
  File renameSync(String newPath) => internalRenameSync(
        newPath,
        followTailLink: true,
        checkType: (Node node) {
          FileSystemEntityType actualType = node.stat.type;
          if (actualType != expectedType) {
            throw actualType == FileSystemEntityType.notFound
                ? common.noSuchFileOrDirectory(path)
                : common.isADirectory(path);
          }
        },
      );

  @override
  Future<File> copy(String newPath) async => copySync(newPath);

  @override
  File copySync(String newPath) {
    FileNode sourceNode = resolvedBacking;
    fileSystem.findNode(
      newPath,
      segmentVisitor: (
        DirectoryNode parent,
        String childName,
        Node child,
        int currentSegment,
        int finalSegment,
      ) {
        if (currentSegment == finalSegment) {
          if (child != null) {
            if (utils.isLink(child)) {
              List<String> ledger = <String>[];
              child = utils.resolveLinks(child, () => newPath, ledger: ledger);
              checkExists(child, () => newPath);
              parent = child.parent;
              childName = ledger.last;
              assert(parent.children.containsKey(childName));
            }
            utils.checkType(expectedType, child.type, () => newPath);
            parent.children.remove(childName);
          }
          FileNode newNode = FileNode(parent);
          newNode.copyFrom(sourceNode);
          parent.children[childName] = newNode;
        }
        return child;
      },
    );
    return clone(newPath);
  }

  @override
  Future<int> length() async => lengthSync();

  @override
  int lengthSync() => (resolvedBacking as FileNode).size;

  @override
  File get absolute => super.absolute;

  @override
  Future<DateTime> lastAccessed() async => lastAccessedSync();

  @override
  DateTime lastAccessedSync() => (resolvedBacking as FileNode).stat.accessed;

  @override
  Future<dynamic> setLastAccessed(DateTime time) async =>
      setLastAccessedSync(time);

  @override
  void setLastAccessedSync(DateTime time) {
    FileNode node = resolvedBacking;
    node.accessed = time.millisecondsSinceEpoch;
  }

  @override
  Future<DateTime> lastModified() async => lastModifiedSync();

  @override
  DateTime lastModifiedSync() => (resolvedBacking as FileNode).stat.modified;

  @override
  Future<dynamic> setLastModified(DateTime time) async =>
      setLastModifiedSync(time);

  @override
  void setLastModifiedSync(DateTime time) {
    FileNode node = resolvedBacking;
    node.modified = time.millisecondsSinceEpoch;
  }

  @override
  Future<io.RandomAccessFile> open(
          {io.FileMode mode = io.FileMode.read}) async =>
      openSync(mode: mode);

  @override
  io.RandomAccessFile openSync({io.FileMode mode = io.FileMode.read}) {
    if (utils.isWriteMode(mode) && !existsSync()) {
      // [resolvedBacking] requires that the file already exists, so we must
      // create it here first.
      createSync();
    }

    return MemoryRandomAccessFile(this, resolvedBacking as FileNode, mode);
  }

  @override
  Stream<Uint8List> openRead([int start, int end]) {
    try {
      FileNode node = resolvedBacking;
      Uint8List content = node.content;
      if (start != null) {
        content = end == null
            ? content.sublist(start)
            : content.sublist(start, math.min(end, content.length));
      }
      return Stream<Uint8List>.fromIterable(<Uint8List>[content]);
    } catch (e) {
      return Stream<Uint8List>.fromFuture(Future<Uint8List>.error(e));
    }
  }

  @override
  io.IOSink openWrite({
    io.FileMode mode = io.FileMode.write,
    Encoding encoding = utf8,
  }) {
    if (!utils.isWriteMode(mode)) {
      throw ArgumentError.value(mode, 'mode',
          'Must be either WRITE, APPEND, WRITE_ONLY, or WRITE_ONLY_APPEND');
    }
    return _FileSink.fromFile(this, mode, encoding);
  }

  @override
  Future<Uint8List> readAsBytes() async => readAsBytesSync();

  @override
  Uint8List readAsBytesSync() =>
      Uint8List.fromList((resolvedBacking as FileNode).content);

  @override
  Future<String> readAsString({Encoding encoding = utf8}) async =>
      readAsStringSync(encoding: encoding);

  @override
  String readAsStringSync({Encoding encoding = utf8}) =>
      encoding.decode(readAsBytesSync());

  @override
  Future<List<String>> readAsLines({Encoding encoding = utf8}) async =>
      readAsLinesSync(encoding: encoding);

  @override
  List<String> readAsLinesSync({Encoding encoding = utf8}) {
    String str = readAsStringSync(encoding: encoding);

    if (str.isEmpty) {
      return <String>[];
    }

    final List<String> lines = str.split('\n');
    if (str.endsWith('\n')) {
      // A final newline should not create an additional line.
      lines.removeLast();
    }

    return lines;
  }

  @override
  Future<File> writeAsBytes(
    List<int> bytes, {
    io.FileMode mode = io.FileMode.write,
    bool flush = false,
  }) async {
    writeAsBytesSync(bytes, mode: mode, flush: flush);
    return this;
  }

  @override
  void writeAsBytesSync(
    List<int> bytes, {
    io.FileMode mode = io.FileMode.write,
    bool flush = false,
  }) {
    if (!utils.isWriteMode(mode)) {
      throw common.badFileDescriptor(path);
    }
    FileNode node = _resolvedBackingOrCreate;
    _truncateIfNecessary(node, mode);
    node.write(bytes);
    node.touch();
  }

  @override
  Future<File> writeAsString(
    String contents, {
    io.FileMode mode = io.FileMode.write,
    Encoding encoding = utf8,
    bool flush = false,
  }) async {
    writeAsStringSync(contents, mode: mode, encoding: encoding, flush: flush);
    return this;
  }

  @override
  void writeAsStringSync(
    String contents, {
    io.FileMode mode = io.FileMode.write,
    Encoding encoding = utf8,
    bool flush = false,
  }) =>
      writeAsBytesSync(encoding.encode(contents), mode: mode, flush: flush);

  @override
  @protected
  File clone(String path) => MemoryFile(fileSystem, path);

  void _truncateIfNecessary(FileNode node, io.FileMode mode) {
    if (mode == io.FileMode.write || mode == io.FileMode.writeOnly) {
      node.clear();
    }
  }

  @override
  String toString() => "MemoryFile: '$path'";
}

/// Implementation of an [io.IOSink] that's backed by a [FileNode].
class _FileSink implements io.IOSink {
  factory _FileSink.fromFile(
    MemoryFile file,
    io.FileMode mode,
    Encoding encoding,
  ) {
    Future<FileNode> node = Future<FileNode>.microtask(() {
      FileNode node = file._resolvedBackingOrCreate;
      file._truncateIfNecessary(node, mode);
      return node;
    });
    return _FileSink._(node, encoding);
  }

  _FileSink._(this._node, this.encoding) {
    _pendingWrites = _node;
  }

  final Future<FileNode> _node;
  final Completer<void> _completer = Completer<void>();

  Future<FileNode> _pendingWrites;
  Completer<void> _streamCompleter;
  bool _isClosed = false;

  @override
  Encoding encoding;

  bool get isStreaming => !(_streamCompleter?.isCompleted ?? true);

  @override
  void add(List<int> data) {
    _checkNotStreaming();
    if (_isClosed) {
      throw StateError('StreamSink is closed');
    }

    _addData(data);
  }

  @override
  void write(Object obj) => add(encoding.encode(obj?.toString() ?? 'null'));

  @override
  void writeAll(Iterable<dynamic> objects, [String separator = '']) {
    bool firstIter = true;
    for (dynamic obj in objects) {
      if (!firstIter && separator != null) {
        write(separator);
      }
      firstIter = false;
      write(obj);
    }
  }

  @override
  void writeln([Object obj = '']) {
    write(obj);
    write('\n');
  }

  @override
  void writeCharCode(int charCode) => write(String.fromCharCode(charCode));

  @override
  void addError(dynamic error, [StackTrace stackTrace]) {
    _checkNotStreaming();
    _completer.completeError(error, stackTrace);
  }

  @override
  Future<void> addStream(Stream<List<int>> stream) {
    _checkNotStreaming();
    _streamCompleter = Completer<void>();
    void finish() {
      _streamCompleter.complete();
      _streamCompleter = null;
    }

    stream.listen(
      (List<int> data) => _addData(data),
      cancelOnError: true,
      onError: (dynamic error, StackTrace stackTrace) {
        _completer.completeError(error, stackTrace);
        finish();
      },
      onDone: finish,
    );
    return _streamCompleter.future;
  }

  @override
  Future<void> flush() {
    _checkNotStreaming();
    return _pendingWrites;
  }

  @override
  Future<void> close() {
    _checkNotStreaming();
    if (!_isClosed) {
      _isClosed = true;
      _pendingWrites.then(
        (_) => _completer.complete(),
        onError: (dynamic error, StackTrace stackTrace) =>
            _completer.completeError(error, stackTrace),
      );
    }
    return _completer.future;
  }

  @override
  Future<void> get done => _completer.future;

  void _addData(List<int> data) {
    _pendingWrites = _pendingWrites.then((FileNode node) {
      node.write(data);
      return node;
    });
  }

  void _checkNotStreaming() {
    if (isStreaming) {
      throw StateError('StreamSink is bound to a stream');
    }
  }
}
