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

import 'package:collection/collection.dart';
import 'package:path/path.dart' as p;
import 'package:term_glyph/term_glyph.dart' as glyph;
import 'package:test/test.dart';

import 'descriptor.dart';
import 'sandbox.dart';
import 'utils.dart';

/// A descriptor describing a single file.
///
/// In addition to the normal descriptor methods, this has [read] and
/// [readAsBytes] methods that allows its contents to be read.
///
/// This may be extended outside this package.
abstract class FileDescriptor extends Descriptor {
  /// Creates a new [FileDescriptor] with [name] and [contents].
  ///
  /// The [contents] may be a `String`, a `List<int>`, or a [Matcher]. If it's a
  /// string, [create] creates a UTF-8 file and [validate] parses the physical
  /// file as UTF-8. If it's a [Matcher], [validate] matches it against the
  /// physical file's contents parsed as UTF-8, and [create], [read], and
  /// [readAsBytes] are unsupported.
  ///
  /// If [contents] isn't passed, [create] creates an empty file and [validate]
  /// verifies that the file is empty.
  ///
  /// To match a [Matcher] against a file's binary contents, use [new
  /// FileDescriptor.binaryMatcher] instead.
  factory FileDescriptor(String name, contents) {
    if (contents is String) return _StringFileDescriptor(name, contents);
    if (contents is List) {
      return _BinaryFileDescriptor(name, contents.cast<int>());
    }
    if (contents == null) return _BinaryFileDescriptor(name, []);
    return _MatcherFileDescriptor(name, contents as Matcher);
  }

  /// Returns a `dart:io` [File] object that refers to this file within
  /// [sandbox].
  File get io => File(p.join(sandbox, name));

  /// Creates a new binary [FileDescriptor] with [name] that matches its binary
  /// contents against [matcher].
  ///
  /// The [create], [read], and [readAsBytes] methods are unsupported for this
  /// descriptor.
  factory FileDescriptor.binaryMatcher(String name, Matcher matcher) =>
      _MatcherFileDescriptor(name, matcher, isBinary: true);

  /// A protected constructor that's only intended for subclasses.
  FileDescriptor.protected(String name) : super(name);

  @override
  Future create([String parent]) async {
    // Create the stream before we call [File.openWrite] because it may fail
    // fast (e.g. if this is a matcher file).
    var file = File(p.join(parent ?? sandbox, name)).openWrite();
    try {
      await readAsBytes().listen(file.add).asFuture();
    } finally {
      await file.close();
    }
  }

  @override
  Future validate([String parent]) async {
    var fullPath = p.join(parent ?? sandbox, name);
    var pretty = prettyPath(fullPath);
    if (!(await File(fullPath).exists())) {
      fail('File not found: "$pretty".');
    }

    await _validate(pretty, await File(fullPath).readAsBytes());
  }

  /// Validates that [binaryContents] matches the expected contents of
  /// the descriptor.
  ///
  /// The [prettyPath] is a human-friendly representation of the path to the
  /// descriptor.
  Future _validate(String prettyPath, List<int> binaryContents);

  /// Reads and decodes the contents of this descriptor as a UTF-8 string.
  ///
  /// This isn't supported for matcher descriptors.
  Future<String> read() => utf8.decodeStream(readAsBytes());

  /// Reads the contents of this descriptor as a byte stream.
  ///
  /// This isn't supported for matcher descriptors.
  Stream<List<int>> readAsBytes();

  @override
  String describe() => name;
}

class _BinaryFileDescriptor extends FileDescriptor {
  /// The contents of this descriptor's file.
  final List<int> _contents;

  _BinaryFileDescriptor(String name, this._contents) : super.protected(name);

  @override
  Stream<List<int>> readAsBytes() => Stream.fromIterable([_contents]);

  @override
  Future _validate(String prettPath, List<int> actualContents) async {
    if (const IterableEquality().equals(_contents, actualContents)) return null;
    // TODO(nweiz): show a hex dump here if the data is small enough.
    fail('File "$prettPath" didn\'t contain the expected binary data.');
  }
}

class _StringFileDescriptor extends FileDescriptor {
  /// The contents of this descriptor's file.
  final String _contents;

  _StringFileDescriptor(String name, this._contents) : super.protected(name);

  @override
  Future<String> read() async => _contents;

  @override
  Stream<List<int>> readAsBytes() =>
      Stream.fromIterable([utf8.encode(_contents)]);

  @override
  Future _validate(String prettyPath, List<int> actualContents) {
    var actualContentsText = utf8.decode(actualContents);
    if (_contents == actualContentsText) return null;
    fail(_textMismatchMessage(prettyPath, _contents, actualContentsText));
  }

  String _textMismatchMessage(
      String prettyPath, String expected, String actual) {
    final expectedLines = expected.split('\n');
    final actualLines = actual.split('\n');

    var results = [];

    // Compare them line by line to see which ones match.
    var length = math.max(expectedLines.length, actualLines.length);
    for (var i = 0; i < length; i++) {
      if (i >= actualLines.length) {
        // Missing output.
        results.add('? ${expectedLines[i]}');
      } else if (i >= expectedLines.length) {
        // Unexpected extra output.
        results.add('X ${actualLines[i]}');
      } else {
        var expectedLine = expectedLines[i];
        var actualLine = actualLines[i];

        if (expectedLine != actualLine) {
          // Mismatched lines.
          results.add('X $actualLine');
        } else {
          // Matched lines.
          results.add('${glyph.verticalLine} $actualLine');
        }
      }
    }

    return 'File "$prettyPath" should contain:\n'
        '${addBar(expected)}\n'
        'but actually contained:\n'
        "${results.join('\n')}";
  }
}

class _MatcherFileDescriptor extends FileDescriptor {
  /// The matcher for this descriptor's contents.
  final Matcher _matcher;

  /// Whether [_matcher] should match against the file's string or byte
  /// contents.
  final bool _isBinary;

  _MatcherFileDescriptor(String name, this._matcher, {bool isBinary = false})
      : _isBinary = isBinary,
        super.protected(name);

  @override
  Stream<List<int>> readAsBytes() =>
      throw UnsupportedError("Matcher files can't be created or read.");

  @override
  Future _validate(String prettyPath, List<int> actualContents) async {
    try {
      expect(
          _isBinary ? actualContents : utf8.decode(actualContents), _matcher);
    } on TestFailure catch (error) {
      fail('Invalid contents for file "$prettyPath":\n${error.message}');
    }
  }
}
