// 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 new _StringFileDescriptor(name, contents);
    if (contents is List) {
      return new _BinaryFileDescriptor(name, DelegatingList.typed(contents));
    }
    if (contents == null) return new _BinaryFileDescriptor(name, []);
    return new _MatcherFileDescriptor(name, contents);
  }

  /// Returns a `dart:io` [File] object that refers to this file within
  /// [sandbox].
  File get io => new 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) =>
      new _MatcherFileDescriptor(name, matcher, isBinary: true);

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

  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 = new File(p.join(parent ?? sandbox, name)).openWrite();
    try {
      await readAsBytes().listen(file.add).asFuture();
    } finally {
      await file.close();
    }
  }

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

    await _validate(pretty, await new 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.
  void _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();

  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);

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

  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);

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

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

  Future _validate(String prettyPath, List<int> actualContents) {
    var actualContentsText = utf8.decode(actualContents);
    if (_contents == actualContentsText) return null;
    throw 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);

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

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